// Copyright 2015 The Vanadium 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 main

import (
	"encoding/json"
	"fmt"
	"strings"
)

// object simplifies the parsing and handling of json objects that are
// unmarshaled into an empty interface.
type object map[string]interface{}

func (o *object) importJSON(data []byte) error {
	var decode interface{}
	if err := json.Unmarshal(data, &decode); err != nil {
		return err
	}
	c := convertToObject(decode)
	var ok bool
	if *o, ok = c.(object); !ok {
		return fmt.Errorf("object is %T", c)
	}
	return nil
}

// convertToObject converts all occurrences of map[string]interface{} to object.
func convertToObject(i interface{}) interface{} {
	switch obj := i.(type) {
	case map[string]interface{}:
		for k, v := range obj {
			obj[k] = convertToObject(v)
		}
		return object(obj)
	case []interface{}:
		for x, y := range obj {
			obj[x] = convertToObject(y)
		}
		return obj
	default:
		return obj
	}
}

func (o object) json() ([]byte, error) {
	return json.MarshalIndent(o, "", "  ")
}

// get retrieves the value of an object inside this object, e.g.:
// if o = { "a": { "b": "c" } }, o.get("a.b") == "c".
func (o object) get(name string) interface{} {
	parts := strings.Split(name, ".")
	var obj interface{} = o
	for _, p := range parts {
		m, ok := obj.(object)
		if !ok {
			return nil
		}
		var exists bool
		if obj, exists = m[p]; !exists {
			return nil
		}
	}
	return obj
}

// set sets the value of an object inside this object, e.g.:
// if o = { "a": { "b": "c" } }, o.set("a.b", "X") change "c" to "X".
func (o object) set(name string, value interface{}) error {
	parts := strings.Split(name, ".")
	var obj interface{} = o
	for {
		m, ok := obj.(object)
		if !ok {
			return fmt.Errorf("%q not an object", name)
		}

		p := parts[0]
		parts = parts[1:]

		if len(parts) == 0 {
			m[p] = value
			break
		}
		if obj, ok = m[p]; !ok {
			obj = make(object)
			m[p] = obj
		}
	}
	return nil
}

// getString retrieves a string object.
func (c object) getString(name string) string {
	switch s := c.get(name).(type) {
	case string:
		return s
	case nil:
		return ""
	default:
		return fmt.Sprintf("%v", s)
	}
}

// getString retrieves a integer object.
func (c object) getInt(name string) int {
	switch v := c.get(name).(type) {
	case int:
		return v
	case float64:
		return int(v)
	default:
		return -1
	}
}

// getObjectArray retrieves an array of objects.
func (c object) getObjectArray(name string) []object {
	s, ok := c.get(name).([]interface{})
	if !ok {
		return nil
	}
	n := make([]object, len(s))
	for i, o := range s {
		if x, ok := o.(object); ok {
			n[i] = x
			continue
		}
		return nil
	}
	return n
}

// append adds objects to an array.
func (c object) append(name string, values ...interface{}) error {
	obj := c.get(name)
	if obj == nil {
		obj = []interface{}{}
	}
	switch array := obj.(type) {
	case []interface{}:
		return c.set(name, append(array, values...))
	default:
		return fmt.Errorf("%q is not an array", name)
	}
}
