package html_bridge

// |@@| C

import (
	erro "gardening/src/lib/error"
	"gardening/src/lib/fetcher"
	"gardening/src/lib/filter"
	formLib "gardening/src/lib/form"
	"gardening/src/lib/form_field"
	"gardening/src/lib/presenter"
	"gitlab.com/ccyrillee/kitcla/components/atoms/inputs"
	"gitlab.com/ccyrillee/kitcla/components/organisms/forms"
	"gitlab.com/ccyrillee/kitcla/components/organisms/tables"
	datLib "gitlab.com/ccyrillee/kitcla/dat"
	"strconv"
)

// ConvertBag Convert FormBag from project lib to the FormBag used into the Html Kit
func ConvertBag(formIn *formLib.FormBag) datLib.FormBag {
	formOut := datLib.FormBag{}
	for _, invalidation := range formIn.Invalidations {
		formOut.Invalidations = append(formOut.Invalidations, &datLib.Invalidation{
			Field:   invalidation.Field,
			Message: invalidation.Message,
		})
	}
	return formOut
}

func ConvertKitToLibFormField(formField *forms.FormField) *presenter.FormField {
	f := &presenter.FormField{
		Key:      formField.Key,
		Label:    formField.Label,
		Hidden:   formField.Hidden,
		Value:    formField.Value,
		Data:     formField.Data,
		Indexes:  formField.Indexes,
		Template: formField.Template,
	}
	for _, child := range formField.Children {
		f.Children = append(f.Children, ConvertKitToLibFormField(child))
	}
	return f
}

func ConvertPagination(fetcherPagination *fetcher.FetcherPagination) *datLib.Pagination {
	return &datLib.Pagination{
		PerPage:       fetcherPagination.PerPage,
		CurrentPage:   fetcherPagination.Page,
		ItemsCount:    fetcherPagination.Total,
		ActiveFilters: ActiveFilters(fetcherPagination.Modulation),
	}
}

func AllowedFilters(mod *fetcher.FetcherMod) []*datLib.Filter {
	var filters []*datLib.Filter
	for _, allowedFilter := range mod.AllowedFilters {
		switch v := allowedFilter.(type) {
		case *filter.IntegerFilter:
			filters = append(filters, integerAllowedFilter(allowedFilter.GetKey()))
		case *filter.StringFilter:
			filters = append(filters, stringAllowedFilter(allowedFilter.GetKey()))
		case *filter.IdFilter:
			filters = append(filters, stringAllowedFilter(allowedFilter.GetKey()))
		case *filter.BooleanFilter:
			filters = append(filters, booleanAllowedFilter(allowedFilter.GetKey()))
		case *filter.RelationIdFilter:
			filters = append(filters, relationIdAllowedFilter(allowedFilter.GetKey()))
		default:
			panic(erro.N("Filter kind is not allowed").KV("type", v))
		}
	}
	return filters
}

func ActiveFilters(mod *fetcher.FetcherMod) []*datLib.ActiveFilter {
	var filters []*datLib.ActiveFilter

	for _, mod := range mod.Filters {
		switch v := mod.(type) {
		case *fetcher.ExactStringValueFilter:
			filter := &datLib.ActiveFilter{
				Kind:         datLib.ActiveFilterKindExactStringValueFilter,
				FilterKey:    v.Column,
				OperationKey: "eq",
				Value:        v.Value,
			}
			filters = append(filters, filter)
		case *fetcher.UnequalStringValueFilter:
			filter := &datLib.ActiveFilter{
				Kind:         datLib.ActiveFilterKindExactStringValueFilter, // FIXME To the correct value
				FilterKey:    v.Column,
				OperationKey: "neq",
				Value:        v.Value,
			}
			filters = append(filters, filter)
		case *fetcher.ContainsStringValueFilter:
			filter := &datLib.ActiveFilter{
				Kind:         datLib.ActiveFilterKindContainsStringValueFilter,
				FilterKey:    v.Column,
				OperationKey: "contains",
				Value:        v.Value,
			}
			filters = append(filters, filter)
		case *fetcher.ExactIntegerValueFilter:
			filter := &datLib.ActiveFilter{
				Kind:         datLib.ActiveFilterKindExactIntegerValueFilter,
				FilterKey:    v.Column,
				OperationKey: "eq",
				Value:        strconv.Itoa(v.Value),
			}
			filters = append(filters, filter)
		case *fetcher.ExactBooleanValueFilter:
			s := "false"
			if v.Value == true {
				s = "true"
			}
			filter := &datLib.ActiveFilter{
				Kind:         datLib.ActiveFilterKindExactBooleanValueFilter,
				FilterKey:    v.Column,
				OperationKey: "eq",
				Value:        s,
			}
			filters = append(filters, filter)
		case *fetcher.InStringValuesFilter:
			// TODO Implement this case later
		case *fetcher.NotInStringValuesFilter:
			// TODO Implement this case later
		default:
			erro.P(erro.N("Unknown filter"))
		}
	}
	return filters
}

func integerAllowedFilter(name string) *datLib.Filter {
	filter := &datLib.Filter{
		Name: name,
		Text: name,
	}
	filter.Operations = append(filter.Operations, &datLib.FilterOperation{
		Name:   "eq",
		Text:   "Is",
		Widget: "integer",
	})
	filter.Operations = append(filter.Operations, &datLib.FilterOperation{
		Name:   "neq",
		Text:   "Is not",
		Widget: "integer",
	})
	return filter
}

func booleanAllowedFilter(name string) *datLib.Filter {
	filter := &datLib.Filter{
		Name: name,
		Text: name,
	}
	filter.Operations = append(filter.Operations, &datLib.FilterOperation{
		Name:   "eq",
		Text:   "Equals",
		Widget: "boolean",
	})
	return filter
}

func relationIdAllowedFilter(name string) *datLib.Filter {
	filter := &datLib.Filter{
		Name: name,
		Text: name,
	}
	filter.Operations = append(filter.Operations, &datLib.FilterOperation{
		Name:   "eq",
		Text:   "Equals",
		Widget: "string",
	})
	return filter
}

func stringAllowedFilter(name string) *datLib.Filter {
	filter := &datLib.Filter{
		Name: name,
		Text: name,
	}
	filter.Operations = append(filter.Operations, &datLib.FilterOperation{
		Name:   "eq",
		Text:   "Equals",
		Widget: "string",
	})
	filter.Operations = append(filter.Operations, &datLib.FilterOperation{
		Name:   "contains",
		Text:   "Contains",
		Widget: "string",
	})
	return filter
}

func TableColumns(columns []*presenter.Column) []*tables.Column {
	var tableColumns []*tables.Column

	for _, column := range columns {
		tableColumns = append(tableColumns, &tables.Column{
			Key:    column.Key,
			Label:  column.Label,
			Kind:   column.Kind,
			Hidden: column.Hidden,
		})
	}
	return tableColumns
}

func FormFields(fields []*presenter.FormField, state string) []*forms.FormField {
	var formFields []*forms.FormField

	for _, presenterFormField := range fields {
		formField := &forms.FormField{
			Key:      presenterFormField.Key,
			Label:    presenterFormField.Label,
			Value:    presenterFormField.Value,
			Data:     presenterFormField.Data,
			Hidden:   presenterFormField.Hidden,
			Template: presenterFormField.Template,
			Indexes:  presenterFormField.Indexes,
		}
		formField.Children = FormFields(presenterFormField.Children, state)
		formFields = append(formFields, formField)
	}
	return formFields
}

func AdvancedSelectInputFilters(filters []form_field.Filter) []inputs.Filter {
	var outFilters []inputs.Filter
	for _, inFilter := range filters {
		outFilters = append(outFilters, inputs.Filter{
			Key:   inFilter.Key,
			Value: inFilter.Value,
		})
	}
	return outFilters
}
