// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package schema

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/internal/configs/hcl2shim"
	"github.com/hashicorp/terraform/internal/legacy/terraform"
	"github.com/mitchellh/copystructure"
)

const TimeoutKey = "e2bfb730-ecaa-11e6-8f88-34363bc7c4c0"
const TimeoutsConfigKey = "timeouts"

const (
	TimeoutCreate  = "create"
	TimeoutRead    = "read"
	TimeoutUpdate  = "update"
	TimeoutDelete  = "delete"
	TimeoutDefault = "default"
)

func timeoutKeys() []string {
	return []string{
		TimeoutCreate,
		TimeoutRead,
		TimeoutUpdate,
		TimeoutDelete,
		TimeoutDefault,
	}
}

// could be time.Duration, int64 or float64
func DefaultTimeout(tx interface{}) *time.Duration {
	var td time.Duration
	switch raw := tx.(type) {
	case time.Duration:
		return &raw
	case int64:
		td = time.Duration(raw)
	case float64:
		td = time.Duration(int64(raw))
	default:
		log.Printf("[WARN] Unknown type in DefaultTimeout: %#v", tx)
	}
	return &td
}

type ResourceTimeout struct {
	Create, Read, Update, Delete, Default *time.Duration
}

// ConfigDecode takes a schema and the configuration (available in Diff) and
// validates, parses the timeouts into `t`
func (t *ResourceTimeout) ConfigDecode(s *Resource, c *terraform.ResourceConfig) error {
	if s.Timeouts != nil {
		raw, err := copystructure.Copy(s.Timeouts)
		if err != nil {
			log.Printf("[DEBUG] Error with deep copy: %s", err)
		}
		*t = *raw.(*ResourceTimeout)
	}

	if raw, ok := c.Config[TimeoutsConfigKey]; ok {
		var rawTimeouts []map[string]interface{}
		switch raw := raw.(type) {
		case map[string]interface{}:
			rawTimeouts = append(rawTimeouts, raw)
		case []map[string]interface{}:
			rawTimeouts = raw
		case string:
			if raw == hcl2shim.UnknownVariableValue {
				// Timeout is not defined in the config
				// Defaults will be used instead
				return nil
			} else {
				log.Printf("[ERROR] Invalid timeout value: %q", raw)
				return fmt.Errorf("Invalid Timeout value found")
			}
		case []interface{}:
			for _, r := range raw {
				if rMap, ok := r.(map[string]interface{}); ok {
					rawTimeouts = append(rawTimeouts, rMap)
				} else {
					// Go will not allow a fallthrough
					log.Printf("[ERROR] Invalid timeout structure: %#v", raw)
					return fmt.Errorf("Invalid Timeout structure found")
				}
			}
		default:
			log.Printf("[ERROR] Invalid timeout structure: %#v", raw)
			return fmt.Errorf("Invalid Timeout structure found")
		}

		for _, timeoutValues := range rawTimeouts {
			for timeKey, timeValue := range timeoutValues {
				// validate that we're dealing with the normal CRUD actions
				var found bool
				for _, key := range timeoutKeys() {
					if timeKey == key {
						found = true
						break
					}
				}

				if !found {
					return fmt.Errorf("Unsupported Timeout configuration key found (%s)", timeKey)
				}

				// Get timeout
				rt, err := time.ParseDuration(timeValue.(string))
				if err != nil {
					return fmt.Errorf("Error parsing %q timeout: %s", timeKey, err)
				}

				var timeout *time.Duration
				switch timeKey {
				case TimeoutCreate:
					timeout = t.Create
				case TimeoutUpdate:
					timeout = t.Update
				case TimeoutRead:
					timeout = t.Read
				case TimeoutDelete:
					timeout = t.Delete
				case TimeoutDefault:
					timeout = t.Default
				}

				// If the resource has not delcared this in the definition, then error
				// with an unsupported message
				if timeout == nil {
					return unsupportedTimeoutKeyError(timeKey)
				}

				*timeout = rt
			}
			return nil
		}
	}

	return nil
}

func unsupportedTimeoutKeyError(key string) error {
	return fmt.Errorf("Timeout Key (%s) is not supported", key)
}

// DiffEncode, StateEncode, and MetaDecode are analogous to the Go stdlib JSONEncoder
// interface: they encode/decode a timeouts struct from an instance diff, which is
// where the timeout data is stored after a diff to pass into Apply.
//
// StateEncode encodes the timeout into the ResourceData's InstanceState for
// saving to state
func (t *ResourceTimeout) DiffEncode(id *terraform.InstanceDiff) error {
	return t.metaEncode(id)
}

func (t *ResourceTimeout) StateEncode(is *terraform.InstanceState) error {
	return t.metaEncode(is)
}

// metaEncode encodes the ResourceTimeout into a map[string]interface{} format
// and stores it in the Meta field of the interface it's given.
// Assumes the interface is either *terraform.InstanceState or
// *terraform.InstanceDiff, returns an error otherwise
func (t *ResourceTimeout) metaEncode(ids interface{}) error {
	m := make(map[string]interface{})

	if t.Create != nil {
		m[TimeoutCreate] = t.Create.Nanoseconds()
	}
	if t.Read != nil {
		m[TimeoutRead] = t.Read.Nanoseconds()
	}
	if t.Update != nil {
		m[TimeoutUpdate] = t.Update.Nanoseconds()
	}
	if t.Delete != nil {
		m[TimeoutDelete] = t.Delete.Nanoseconds()
	}
	if t.Default != nil {
		m[TimeoutDefault] = t.Default.Nanoseconds()
		// for any key above that is nil, if default is specified, we need to
		// populate it with the default
		for _, k := range timeoutKeys() {
			if _, ok := m[k]; !ok {
				m[k] = t.Default.Nanoseconds()
			}
		}
	}

	// only add the Timeout to the Meta if we have values
	if len(m) > 0 {
		switch instance := ids.(type) {
		case *terraform.InstanceDiff:
			if instance.Meta == nil {
				instance.Meta = make(map[string]interface{})
			}
			instance.Meta[TimeoutKey] = m
		case *terraform.InstanceState:
			if instance.Meta == nil {
				instance.Meta = make(map[string]interface{})
			}
			instance.Meta[TimeoutKey] = m
		default:
			return fmt.Errorf("Error matching type for Diff Encode")
		}
	}

	return nil
}

func (t *ResourceTimeout) StateDecode(id *terraform.InstanceState) error {
	return t.metaDecode(id)
}
func (t *ResourceTimeout) DiffDecode(is *terraform.InstanceDiff) error {
	return t.metaDecode(is)
}

func (t *ResourceTimeout) metaDecode(ids interface{}) error {
	var rawMeta interface{}
	var ok bool
	switch rawInstance := ids.(type) {
	case *terraform.InstanceDiff:
		rawMeta, ok = rawInstance.Meta[TimeoutKey]
		if !ok {
			return nil
		}
	case *terraform.InstanceState:
		rawMeta, ok = rawInstance.Meta[TimeoutKey]
		if !ok {
			return nil
		}
	default:
		return fmt.Errorf("Unknown or unsupported type in metaDecode: %#v", ids)
	}

	times := rawMeta.(map[string]interface{})
	if len(times) == 0 {
		return nil
	}

	if v, ok := times[TimeoutCreate]; ok {
		t.Create = DefaultTimeout(v)
	}
	if v, ok := times[TimeoutRead]; ok {
		t.Read = DefaultTimeout(v)
	}
	if v, ok := times[TimeoutUpdate]; ok {
		t.Update = DefaultTimeout(v)
	}
	if v, ok := times[TimeoutDelete]; ok {
		t.Delete = DefaultTimeout(v)
	}
	if v, ok := times[TimeoutDefault]; ok {
		t.Default = DefaultTimeout(v)
	}

	return nil
}
