// Copyright 2019 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 repo

import (
	"encoding/json"
	"fmt"

	tuf_data "github.com/flynn/go-tuf/data"
)

// Config is a struct that mirrors an associated FIDL table
// definition in //sdk/fidl/fuchsia.pkg/repo.fidl. Documentation is as in
// that file. Ditto for the types that comprise its definition.
//
// Keep these in sync with their repo.fidl counterparts as well as the custom
//
type Config struct {
	URL              string         `json:"repo_url"`
	RootKeys         []KeyConfig    `json:"root_keys"`
	Mirrors          []MirrorConfig `json:"mirrors"`
	RootVersion      uint32         `json:"root_version"`
	RootThreshold    uint32         `json:"root_threshold"`
	UpdatePackageURL string         `json:"update_package_url,omitempty"`
}

type MirrorConfig struct {
	URL       string `json:"mirror_url"`
	Subscribe bool   `json:"subscribe"`
	BlobURL   string `json:"blob_mirror_url,omitempty"`
}

type KeyConfig struct {
	// ED25519Key is a 32-byte, lowercase, hex-encoded key.
	ED25519Key string
}

// We replicate the serialization/deserialization logic given in
// //src/sys/pkg/lib/fidl-fuchsia-pkg-ext/src/repo.rs;
// Per this logic, we set the BlobURL field in MirrorConfig as omitempty (above),
// and give custom marshaling logic to the key config.
//

// This alias allows to make use of the default (un)marshalling logic of Config as we redefine it.
type config Config

func (cfg *Config) MarshalJSON() ([]byte, error) {
	cfg2 := config(*cfg)
	if cfg2.RootVersion == 0 {
		cfg2.RootVersion = 1
	}
	if cfg2.RootThreshold == 0 {
		cfg2.RootThreshold = 1
	}
	return json.Marshal(&cfg2)
}

func (cfg *Config) UnmarshalJSON(data []byte) error {
	var cfg2 config
	if err := json.Unmarshal(data, &cfg2); err != nil {
		return err
	}
	if cfg2.RootVersion == 0 {
		cfg2.RootVersion = 1
	}
	if cfg2.RootThreshold == 0 {
		cfg2.RootThreshold = 1
	}
	*cfg = Config(cfg2)
	return nil
}

type typeAndValue struct {
	Type  string `json:"type"`
	Value string `json:"value"`
}

func (key *KeyConfig) MarshalJSON() ([]byte, error) {
	return json.Marshal(&typeAndValue{
		Type:  tuf_data.KeyTypeEd25519,
		Value: key.ED25519Key,
	})
}

func (key *KeyConfig) UnmarshalJSON(data []byte) error {
	var tv typeAndValue
	if err := json.Unmarshal(data, &tv); err != nil {
		return err
	}

	switch tv.Type {
	case tuf_data.KeyTypeEd25519:
		key.ED25519Key = tv.Value
		return nil
	default:
		return fmt.Errorf("unexpected key type: %q", tv.Type)
	}
}

// GetRootKeys returns the list of public key config objects as read from the
// contents of a repository's root metadata file.
func GetRootKeys(root *tuf_data.Root) ([]KeyConfig, error) {
	var rootKeys []KeyConfig
	for _, k := range root.UniqueKeys()["root"] {
		v := k.Value.Public.String()
		var key KeyConfig
		switch k.Type {
		case tuf_data.KeyTypeEd25519:
			key.ED25519Key = v
		default:
			return nil, fmt.Errorf("unexpected key type: %q", k.Type)
		}
		rootKeys = append(rootKeys, key)
	}
	return rootKeys, nil
}
