package genesis

import (
	"encoding/json"
	"errors"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/hexutil"
)

// MarshalJSON marshals as JSON.
func (g *GenesisBlock) MarshalJSON() ([]byte, error) {
	type Genesis struct {
		ChainId   uint64                    `json:"chainId"`
		Timestamp uint64                    `json:"timestamp"`
		ExtraData hexutil.Bytes             `json:"extraData"`
		Alloc     map[string]GenesisAccount `json:"accounts"`
	}
	var enc Genesis
	enc.Timestamp = g.Timestamp
	enc.ExtraData = g.ExtraData
	enc.ChainId = g.ChainId
	if g.AllocInfo != nil {
		enc.Alloc = make(map[string]GenesisAccount, len(g.AllocInfo))
		for k, v := range g.AllocInfo {
			enc.Alloc[k.String()] = v
		}
	}
	return json.Marshal(&enc)
}

// UnmarshalJSON unmarshals from JSON.
func (g *GenesisBlock) UnmarshalJSON(input []byte) error {
	type Genesis struct {
		ChainId   uint64                            `json:"chainId"`
		Timestamp uint64                            `json:"timestamp"`
		ExtraData *hexutil.Bytes                    `json:"extraData"`
		Alloc     map[common.Address]GenesisAccount `json:"accounts"`
	}
	var dec Genesis
	if err := json.Unmarshal(input, &dec); err != nil {
		return err
	}
	g.Timestamp = dec.Timestamp

	if dec.ExtraData != nil {
		g.ExtraData = *dec.ExtraData
	}
	g.ChainId = dec.ChainId
	if dec.Alloc == nil {
		return errors.New("missing required field 'alloc' for Genesis")
	}
	g.AllocInfo = make(GenesisAlloc, len(dec.Alloc))
	for k, v := range dec.Alloc {
		g.AllocInfo[k] = v
	}
	return nil
}
