package graphdriver // import "github.com/docker/docker/daemon/graphdriver"

import (
	"errors"
	"fmt"
	"io"

	"github.com/docker/docker/pkg/archive"
	"github.com/docker/docker/pkg/idtools"
	"github.com/docker/docker/pkg/plugingetter"
	"github.com/docker/docker/pkg/plugins"
)

type graphDriverProxy struct {
	name   string
	p      plugingetter.CompatPlugin
	caps   Capabilities
	client *plugins.Client
}

type graphDriverRequest struct {
	ID         string            `json:",omitempty"`
	Parent     string            `json:",omitempty"`
	MountLabel string            `json:",omitempty"`
	StorageOpt map[string]string `json:",omitempty"`
}

type graphDriverResponse struct {
	Err          string            `json:",omitempty"`
	Dir          string            `json:",omitempty"`
	Exists       bool              `json:",omitempty"`
	Status       [][2]string       `json:",omitempty"`
	Changes      []archive.Change  `json:",omitempty"`
	Size         int64             `json:",omitempty"`
	Metadata     map[string]string `json:",omitempty"`
	Capabilities Capabilities      `json:",omitempty"`
}

type graphDriverInitRequest struct {
	Home string
	Opts []string `json:"Opts"`
	idtools.IdentityMapping
}

func (d *graphDriverProxy) Init(home string, opts []string, idMap idtools.IdentityMapping) error {
	if !d.p.IsV1() {
		if cp, ok := d.p.(plugingetter.CountedPlugin); ok {
			// always acquire here, it will be cleaned up on daemon shutdown
			cp.Acquire()
		}
	}
	args := &graphDriverInitRequest{
		Home:            home,
		Opts:            opts,
		IdentityMapping: idMap,
	}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.Init", args, &ret); err != nil {
		return err
	}
	if ret.Err != "" {
		return errors.New(ret.Err)
	}
	caps, err := d.fetchCaps()
	if err != nil {
		return err
	}
	d.caps = caps
	return nil
}

func (d *graphDriverProxy) fetchCaps() (Capabilities, error) {
	args := &graphDriverRequest{}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.Capabilities", args, &ret); err != nil {
		if !plugins.IsNotFound(err) {
			return Capabilities{}, err
		}
	}
	return ret.Capabilities, nil
}

func (d *graphDriverProxy) String() string {
	return d.name
}

func (d *graphDriverProxy) Capabilities() Capabilities {
	return d.caps
}

func (d *graphDriverProxy) CreateReadWrite(id, parent string, opts *CreateOpts) error {
	return d.create("GraphDriver.CreateReadWrite", id, parent, opts)
}

func (d *graphDriverProxy) Create(id, parent string, opts *CreateOpts) error {
	return d.create("GraphDriver.Create", id, parent, opts)
}

func (d *graphDriverProxy) create(method, id, parent string, opts *CreateOpts) error {
	args := &graphDriverRequest{
		ID:     id,
		Parent: parent,
	}
	if opts != nil {
		args.MountLabel = opts.MountLabel
		args.StorageOpt = opts.StorageOpt
	}
	var ret graphDriverResponse
	if err := d.client.Call(method, args, &ret); err != nil {
		return err
	}
	if ret.Err != "" {
		return errors.New(ret.Err)
	}
	return nil
}

func (d *graphDriverProxy) Remove(id string) error {
	args := &graphDriverRequest{ID: id}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.Remove", args, &ret); err != nil {
		return err
	}
	if ret.Err != "" {
		return errors.New(ret.Err)
	}
	return nil
}

func (d *graphDriverProxy) Get(id, mountLabel string) (string, error) {
	args := &graphDriverRequest{
		ID:         id,
		MountLabel: mountLabel,
	}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.Get", args, &ret); err != nil {
		return "", err
	}
	var err error
	if ret.Err != "" {
		err = errors.New(ret.Err)
	}
	return d.p.ScopedPath(ret.Dir), err
}

func (d *graphDriverProxy) Put(id string) error {
	args := &graphDriverRequest{ID: id}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.Put", args, &ret); err != nil {
		return err
	}
	if ret.Err != "" {
		return errors.New(ret.Err)
	}
	return nil
}

func (d *graphDriverProxy) Exists(id string) bool {
	args := &graphDriverRequest{ID: id}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.Exists", args, &ret); err != nil {
		return false
	}
	return ret.Exists
}

func (d *graphDriverProxy) Status() [][2]string {
	args := &graphDriverRequest{}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.Status", args, &ret); err != nil {
		return nil
	}
	return ret.Status
}

func (d *graphDriverProxy) GetMetadata(id string) (map[string]string, error) {
	args := &graphDriverRequest{
		ID: id,
	}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.GetMetadata", args, &ret); err != nil {
		return nil, err
	}
	if ret.Err != "" {
		return nil, errors.New(ret.Err)
	}
	return ret.Metadata, nil
}

func (d *graphDriverProxy) Cleanup() error {
	if !d.p.IsV1() {
		if cp, ok := d.p.(plugingetter.CountedPlugin); ok {
			// always release
			defer cp.Release()
		}
	}

	args := &graphDriverRequest{}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.Cleanup", args, &ret); err != nil {
		return nil
	}
	if ret.Err != "" {
		return errors.New(ret.Err)
	}
	return nil
}

func (d *graphDriverProxy) Diff(id, parent string) (io.ReadCloser, error) {
	args := &graphDriverRequest{
		ID:     id,
		Parent: parent,
	}
	body, err := d.client.Stream("GraphDriver.Diff", args)
	if err != nil {
		return nil, err
	}
	return body, nil
}

func (d *graphDriverProxy) Changes(id, parent string) ([]archive.Change, error) {
	args := &graphDriverRequest{
		ID:     id,
		Parent: parent,
	}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.Changes", args, &ret); err != nil {
		return nil, err
	}
	if ret.Err != "" {
		return nil, errors.New(ret.Err)
	}

	return ret.Changes, nil
}

func (d *graphDriverProxy) ApplyDiff(id, parent string, diff io.Reader) (int64, error) {
	var ret graphDriverResponse
	if err := d.client.SendFile(fmt.Sprintf("GraphDriver.ApplyDiff?id=%s&parent=%s", id, parent), diff, &ret); err != nil {
		return -1, err
	}
	if ret.Err != "" {
		return -1, errors.New(ret.Err)
	}
	return ret.Size, nil
}

func (d *graphDriverProxy) DiffSize(id, parent string) (int64, error) {
	args := &graphDriverRequest{
		ID:     id,
		Parent: parent,
	}
	var ret graphDriverResponse
	if err := d.client.Call("GraphDriver.DiffSize", args, &ret); err != nil {
		return -1, err
	}
	if ret.Err != "" {
		return -1, errors.New(ret.Err)
	}
	return ret.Size, nil
}
