// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package control_server

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"runtime"

	"fidl/fuchsia/amber"

	"amber/daemon"
	"amber/metrics"
	"amber/sys_update"

	"syscall/zx"
)

type ControlServer struct {
	daemon    *daemon.Daemon
	sysUpdate *sys_update.SystemUpdateMonitor
}

type EventsImpl struct{}

var _ = amber.Events(EventsImpl{})

var merklePat = regexp.MustCompile("^[0-9a-f]{64}$")

func NewControlServer(d *daemon.Daemon, sum *sys_update.SystemUpdateMonitor) *ControlServer {
	return &ControlServer{
		daemon:    d,
		sysUpdate: sum,
	}
}

func (c *ControlServer) DoTest(in int32) (out string, err error) {
	r := fmt.Sprintf("Your number was %d\n", in)
	return r, nil
}

func (c *ControlServer) GetProcessState(wr zx.Channel) error {
	if err := dumpStacks(wr); err != nil {
		log.Printf("control_server: stack dump failed: %s", err)
	}
	return nil
}

func dumpStacks(ch zx.Channel) error {
	defer ch.Close()
	buf := make([]byte, 1024)
	for {
		n := runtime.Stack(buf, true)
		if n < len(buf) {
			break
		}
		buf = make([]byte, 2*len(buf))
	}

	chunks := chunkBuffer(buf, 63*1024)
	for _, chunk := range chunks {
		err := ch.Write(chunk, []zx.Handle{}, 0)
		if err != nil {
			return fmt.Errorf("control_server: write to channel failed: %s", err)
		}
	}
	return nil
}

func chunkBuffer(buf []byte, chunkSize int) [][]byte {
	if chunkSize < 1 {
		panic(fmt.Sprintf("chunk size of %d is invalid, must be greater than 0", chunkSize))
	}

	chunks := [][]byte{}
	for sent := 0; sent < len(buf); {
		if len(buf)-sent < chunkSize {
			chunkSize = len(buf) - sent
		}
		chunks = append(chunks, buf[sent:sent+chunkSize])
		sent += chunkSize
	}
	return chunks
}

func (c *ControlServer) AddSrc(cfg amber.SourceConfig) (bool, error) {
	if err := c.daemon.AddSource(&cfg); err != nil {
		log.Printf("error adding source: %s", err)
		return false, nil
	}

	return true, nil
}

func (c *ControlServer) CheckForSystemUpdate() (bool, error) {
	go c.sysUpdate.Check(metrics.InitiatorManual)
	return true, nil
}

func (c *ControlServer) RemoveSrc(id string) (amber.Status, error) {
	return c.daemon.RemoveSource(id)
}

func (c *ControlServer) ListSrcs() ([]amber.SourceConfig, error) {
	m := c.daemon.GetSources()
	v := make([]amber.SourceConfig, 0, len(m))
	for _, src := range m {
		c := *src.GetConfig()
		c.StatusConfig.Enabled = src.Enabled()
		v = append(v, c)
	}

	return v, nil
}

func (c *ControlServer) GetUpdateComplete(name string, ver, mer *string) (zx.Channel, error) {
	r, ch, e := zx.NewChannel(0)
	if e != nil {
		log.Printf("Could not create channel")
		// TODO(raggi): the client is just going to get peer closed, and no indication of why
		return zx.Channel(zx.HandleInvalid), e
	}

	if len(name) == 0 {
		return zx.Channel(zx.HandleInvalid), fmt.Errorf("No package name provided")
	}

	var (
		version string
		merkle  string
	)

	if ver != nil {
		version = *ver
	}
	if mer != nil {
		merkle = *mer
	}

	go func() {
		c.daemon.UpdateIfStale()

		root, length, err := c.daemon.MerkleFor(name, version, merkle)
		if err != nil {
			log.Printf("control_server: could not get update for %s: %s", filepath.Join(name, version, merkle), err)
			ch.Handle().SignalPeer(0, zx.SignalUser0)
			ch.Write([]byte(err.Error()), []zx.Handle{}, 0)
			ch.Close()
			return
		}

		if _, err := os.Stat(filepath.Join("/pkgfs/versions", root)); err == nil {
			ch.Write([]byte(root), []zx.Handle{}, 0)
			ch.Close()
			return
		}

		log.Printf("control_server: get update: %s", filepath.Join(name, version, merkle))

		c.daemon.AddWatch(root, func(root string, err error) {
			if os.IsExist(err) {
				log.Printf("control_server: %s already installed", filepath.Join(name, version, root))
				// signal success to the client
				err = nil
			}
			if err != nil {
				log.Printf("control_server: error downloading package: %s", err)
				ch.Handle().SignalPeer(0, zx.SignalUser0)
				ch.Write([]byte(err.Error()), []zx.Handle{}, 0)
				ch.Close()
				return
			}
			ch.Write([]byte(root), []zx.Handle{}, 0)
			ch.Close()
			return
		})

		// errors are handled by the watcher callback
		c.daemon.GetPkg(root, length)
	}()

	return r, nil
}

func (c *ControlServer) PackagesActivated(merkle []string) error {
	log.Printf("control_server: packages activated %s", merkle)
	for _, m := range merkle {
		c.daemon.Activated(m)
	}
	return nil
}

func (c *ControlServer) PackagesFailed(merkle []string, status int32, blobMerkle string) error {
	log.Printf("control_server: packages failed %s due to blob %s, status: %d", merkle, blobMerkle, status)
	for _, m := range merkle {
		c.daemon.Failed(m, zx.Status(status))
	}
	return nil
}

func (c *ControlServer) SetSrcEnabled(id string, enabled bool) (amber.Status, error) {
	if enabled {
		if err := c.daemon.EnableSource(id); err != nil {
			return amber.StatusErr, nil
		}
	} else {
		if err := c.daemon.DisableSource(id); err != nil {
			return amber.StatusErr, nil
		}
	}
	return amber.StatusOk, nil
}

func (c *ControlServer) GetBlob(merkle string) error {
	log.Printf("control_server: blob requested: %q", merkle)
	if !merklePat.MatchString(merkle) {
		return fmt.Errorf("%q is not a valid merkle root", merkle)
	}

	go c.daemon.GetBlob(merkle)

	return nil
}

func (c *ControlServer) Login(srcId string) (*amber.DeviceCode, error) {
	return c.daemon.Login(srcId)
}

func (c *ControlServer) Gc() error {
	return c.daemon.GC()
}
