// Copyright 2019 CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cue

import (
	"bytes"
	"compress/gzip"
	"encoding/gob"
	"path/filepath"
	"strings"

	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/ast/astutil"
	"cuelang.org/go/cue/build"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/format"
	"cuelang.org/go/cue/token"
	"cuelang.org/go/internal"
	"cuelang.org/go/internal/core/export"
)

// root.
type instanceData struct {
	Root  bool
	Path  string
	Files []fileData
}

type fileData struct {
	Name string
	Data []byte
}

const version = 1

type unmarshaller struct {
	ctxt    *build.Context
	imports map[string]*instanceData
}

func (b *unmarshaller) load(pos token.Pos, path string) *build.Instance {
	bi := b.imports[path]
	if bi == nil {
		return nil
	}
	return b.build(bi)
}

func (b *unmarshaller) build(bi *instanceData) *build.Instance {
	p := b.ctxt.NewInstance(bi.Path, b.load)
	p.ImportPath = bi.Path
	for _, f := range bi.Files {
		_ = p.AddFile(f.Name, f.Data)
	}
	p.Complete()
	return p
}

func compileInstances(r *Runtime, data []*instanceData) (instances []*Instance, err error) {
	b := unmarshaller{
		ctxt:    build.NewContext(),
		imports: map[string]*instanceData{},
	}
	for _, i := range data {
		if i.Path == "" {
			if !i.Root {
				return nil, errors.Newf(token.NoPos,
					"data contains non-root package without import path")
			}
			continue
		}
		b.imports[i.Path] = i
	}

	builds := []*build.Instance{}
	for _, i := range data {
		if !i.Root {
			continue
		}
		builds = append(builds, b.build(i))
	}

	return r.build(builds)
}

// Unmarshal creates an Instance from bytes generated by the MarshalBinary
// method of an instance.
func (r *Runtime) Unmarshal(b []byte) ([]*Instance, error) {
	if len(b) == 0 {
		return nil, errors.Newf(token.NoPos, "unmarshal failed: empty buffer")
	}

	switch b[0] {
	case version:
	default:
		return nil, errors.Newf(token.NoPos,
			"unmarshal failed: unsupported version %d, regenerate data", b[0])
	}

	reader, err := gzip.NewReader(bytes.NewReader(b[1:]))
	if err != nil {
		return nil, errors.Newf(token.NoPos, "unmarshal failed: %v", err)
	}

	data := []*instanceData{}
	err = gob.NewDecoder(reader).Decode(&data)
	if err != nil {
		return nil, errors.Newf(token.NoPos, "unmarshal failed: %v", err)
	}

	return compileInstances(r, data)
}

// Marshal creates bytes from a group of instances. Imported instances will
// be included in the emission.
//
// The stored instances are functionally the same, but preserving of file
// information is only done on a best-effort basis.
func (r *Runtime) Marshal(instances ...*Instance) (b []byte, err error) {
	ctx := newContext(r.index())

	staged := []instanceData{}
	done := map[string]int{}

	var errs errors.Error

	var stageInstance func(i *Instance) (pos int)
	stageInstance = func(i *Instance) (pos int) {
		if p, ok := done[i.ImportPath]; ok {
			return p
		}
		// TODO: support exporting instance
		file, _ := export.Def(r.idx.Runtime, i.inst.ID(), i.root)
		imports := []string{}
		file.VisitImports(func(i *ast.ImportDecl) {
			for _, spec := range i.Specs {
				info, _ := astutil.ParseImportSpec(spec)
				imports = append(imports, info.ID)
			}
		})

		if i.PkgName != "" {
			p, name, _ := internal.PackageInfo(file)
			if p == nil {
				pkg := &ast.Package{Name: ast.NewIdent(i.PkgName)}
				file.Decls = append([]ast.Decl{pkg}, file.Decls...)
			} else if name != i.PkgName {
				// p is guaranteed to be generated by Def, so it is "safe" to
				// modify.
				p.Name = ast.NewIdent(i.PkgName)
			}
		}

		b, err := format.Node(file)
		errs = errors.Append(errs, errors.Promote(err, "marshal"))

		filename := "unmarshal"
		if i.inst != nil && len(i.inst.Files) == 1 {
			filename = i.inst.Files[0].Filename

			dir := i.Dir
			if i.inst != nil && i.inst.Root != "" {
				dir = i.inst.Root
			}
			if dir != "" {
				filename = filepath.FromSlash(filename)
				filename, _ = filepath.Rel(dir, filename)
				filename = filepath.ToSlash(filename)
			}
		}
		// TODO: this should probably be changed upstream, but as the path
		// is for reference purposes only, this is safe.
		importPath := filepath.ToSlash(i.ImportPath)

		staged = append(staged, instanceData{
			Path:  importPath,
			Files: []fileData{{filename, b}},
		})

		p := len(staged) - 1

		for _, imp := range imports {
			i := getImportFromPath(ctx.index, imp)
			if i == nil || !strings.Contains(imp, ".") {
				continue // a builtin package.
			}
			stageInstance(i)
		}

		return p
	}

	for _, i := range instances {
		staged[stageInstance(i)].Root = true
	}

	buf := &bytes.Buffer{}
	buf.WriteByte(version)

	zw := gzip.NewWriter(buf)
	if err := gob.NewEncoder(zw).Encode(staged); err != nil {
		return nil, err
	}

	if err := zw.Close(); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil

}
