// 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 component

import (
	"fmt"
	"sync"
	"syscall/zx"
	"syscall/zx/fdio"
	"syscall/zx/fidl"

	"fidl/fuchsia/io"
	"fidl/fuchsia/sys"
)

// #include "zircon/process.h"
import "C"

const (
	HandleDirectoryRequest HandleType = 0x3B
	HandleAppServices      HandleType = 0x43

	HandleUser0 HandleType = 0xF0
	HandleUser1 HandleType = 0xF1
	HandleUser2 HandleType = 0xF2
)

type HandleType uint16

type HandleInfo struct {
	Type HandleType
	Arg  uint16
}

func GetStartupHandle(info HandleInfo) zx.Handle {
	id := uint32(info.Arg)<<16 | uint32(info.Type)
	h := C.zx_take_startup_handle(C.uint32_t(id))
	return zx.Handle(h)
}

type Connector struct {
	serviceRoot zx.Handle
}

type OutDirectory mapDirectory

func (od OutDirectory) getMapDirectory(name string) mapDirectory {
	if dir, ok := od[name]; ok {
		if dir, ok := dir.(*DirectoryWrapper); ok {
			if dir, ok := dir.Directory.(mapDirectory); ok {
				return dir
			}
			panic(fmt.Sprintf("unexpected %s type %T", name, dir))
		}
		panic(fmt.Sprintf("unexpected %s type %T", name, dir))
	}
	dir := make(mapDirectory)
	od[name] = &DirectoryWrapper{
		Directory: dir,
	}
	return dir
}

func (od OutDirectory) AddDebug(name string, n Node) {
	od.getMapDirectory("debug")[name] = n
}

func (od OutDirectory) AddDiagnostics(name string, n Node) {
	od.getMapDirectory("diagnostics")[name] = n
}

func (od OutDirectory) AddService(name string, addFn addFn) {
	od.getMapDirectory("svc")[name] = &Service{AddFn: addFn}
}

type Context struct {
	connector   Connector
	environment struct {
		sync.Once
		*sys.EnvironmentWithCtxInterface
	}
	launcher struct {
		sync.Once
		*sys.LauncherWithCtxInterface
	}
	OutgoingService OutDirectory
}

// NewContextFromStartupInfo connects to the service root directory and registers
// debug services.
func NewContextFromStartupInfo() *Context {
	c0, c1, err := zx.NewChannel(0)
	if err != nil {
		panic(err)
	}

	// TODO(tamird): use "/svc" once it no longer causes crashes.
	if err := fdio.ServiceConnect("/svc/.", zx.Handle(c0)); err != nil {
		panic(err)
	}
	c := &Context{
		connector: Connector{
			serviceRoot: zx.Handle(c1),
		},
		OutgoingService: make(OutDirectory),
	}

	c.OutgoingService.AddDebug("pprof", &DirectoryWrapper{Directory: &pprofDirectory{}})

	return c
}

// BindStartupHandle takes the startup handle if it's not already taken and
// serves the out directory with all services that have been registered on
// (*Context).OutgoingService thus far.
//
// New services added to OutgoingService after BindStartupHandle is called will
// likely not be exposed to the parent component, since they weren't enumerated
// in the response to the initial directory listing call on the directory
// request.
//
// BindStartupHandle never returns.
func (c *Context) BindStartupHandle(ctx fidl.Context) {
	if directoryRequest := GetStartupHandle(HandleInfo{
		Type: HandleDirectoryRequest,
		Arg:  0,
	}); directoryRequest.IsValid() {
		if err := (&DirectoryWrapper{
			Directory: mapDirectory(c.OutgoingService),
		}).addConnection(ctx, 0, 0, io.NodeWithCtxInterfaceRequest{
			Channel: zx.Channel(directoryRequest),
		}); err != nil {
			panic(err)
		}
	}
	<-ctx.Done()
}

func (c *Context) Connector() *Connector {
	return &c.connector
}

func (c *Context) Environment() *sys.EnvironmentWithCtxInterface {
	c.environment.Do(func() {
		r, p, err := sys.NewEnvironmentWithCtxInterfaceRequest()
		if err != nil {
			panic(err)
		}
		c.environment.EnvironmentWithCtxInterface = p
		c.Connector().ConnectToEnvService(r)
	})
	return c.environment.EnvironmentWithCtxInterface
}

func (c *Context) Launcher() *sys.LauncherWithCtxInterface {
	c.launcher.Do(func() {
		r, p, err := sys.NewLauncherWithCtxInterfaceRequest()
		if err != nil {
			panic(err)
		}
		c.launcher.LauncherWithCtxInterface = p
		c.Connector().ConnectToEnvService(r)
	})
	return c.launcher.LauncherWithCtxInterface
}

func (c *Context) ConnectToEnvService(r fidl.ServiceRequest) {
	c.Connector().ConnectToEnvService(r)
}

func (c *Connector) ConnectToEnvService(r fidl.ServiceRequest) {
	if err := fdio.ServiceConnectAt(c.serviceRoot, r.Name(), zx.Handle(r.ToChannel())); err != nil {
		panic(err)
	}
}
