package config

import (
	"reflect"

	"github.com/imdario/mergo"
)

// ThisPathConfig is struct for This in paths yaml
type ThisPathConfig struct {
	Navname *string     `yaml:"Navname"`
	GoTo    *string     `yaml:"GoTo"`
	Data    interface{} `yaml:"Data"`
}

// IndexConfig describes index input and output file
type IndexConfig struct {
	InputFile   *string `yaml:"InputFile"`
	InputString *string `yaml:"InputString"`
	OutputFile  *string `yaml:"OutputFile"`
}

// MetaData describes meta data for current site/tree node
type MetaData struct {
	Title       *string `yaml:"Title"`
	Description *string `yaml:"Description"`
	Keywords    *string `yaml:"Keywords"`
}

// DirnameConfig describes how to handle directory names
type DirnameConfig struct {
	Strip        *string `yaml:"Strip"`
	IgnoreForNav *string `yaml:"IgnoreForNav"`
}

// FilenameConfig describes how to handle filenames
type FilenameConfig struct {
	Strip           *string `yaml:"Strip"`
	Ignore          *string `yaml:"Ignore"`
	OutputExtension *string `yaml:"OutputExtension"`
}

// MarkdownConfig describes markdown handling
type MarkdownConfig struct {
	ChromaRenderer *bool   `yaml:"ChromaRenderer"`
	ChromaStyle    *string `yaml:"ChromaStyle"`
}

// ImagingConfig defines parameter for imaging processing
type ImagingConfig struct {
	Width   int    `yaml:"Width"`
	Height  int    `yaml:"Height"`
	Process string `yaml:"Process"`
	Anchor  string `yaml:"Anchor"`
	Quality int    `yaml:"Quality"`

	Filename string `yaml:"-"`
	Format   string `yaml:"-"`
}

// PathConfig of subdir
type PathConfig struct {
	This     ThisPathConfig  `yaml:"This"`
	Template *string         `yaml:"Template"`
	Index    *IndexConfig    `yaml:"Index"`
	Meta     *MetaData       `yaml:"Meta"`
	Path     *DirnameConfig  `yaml:"Path"`
	Filename *FilenameConfig `yaml:"Filename"`
	Markdown *MarkdownConfig `yaml:"Markdown"`
	Imaging  *ImagingConfig  `yaml:"Imaging"`

	Data map[string]interface{} `yaml:"Data"`
}

// PathConfigTree is complete config tree of content dir
type PathConfigTree struct {
	InputPath  string
	OutputPath string
	Hidden     bool // for collections which are not part of the navigation

	InputFiles []string
	OtherFiles []string

	Config *PathConfig
	Sub    []*PathConfigTree
}

type ptrTransformer struct{}

func (t ptrTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
	if typ.Kind() == reflect.Ptr {
		return func(dst, src reflect.Value) error {
			if dst.CanSet() {
				if dst.IsNil() {
					dst.Set(src)
				}
			}
			return nil
		}
	}
	return nil
}

// Merge merges 2 objects or maps
func Merge(dst, src interface{}) error {
	return mergo.Merge(dst, src, mergo.WithTransformers(ptrTransformer{}))
}
