package mapping

import (
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/layoutauthoringv1"
	runtimev1 "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/runtime/v1"
)

func toWireLayoutAuthoringChanges(changes semantic.LayoutDocumentChanges) *runtimev1.LayoutAuthoringDocumentChanges {
	return &runtimev1.LayoutAuthoringDocumentChanges{
		Name: toWireLayoutAuthoringStringChange(changes.Name), Kind: toWireLayoutAuthoringStringChange(changes.Kind),
		LayoutVersion:        toWireLayoutAuthoringUint32Change(changes.LayoutVersion),
		CompactFields:        toWireLayoutAuthoringStringListChange(changes.CompactFields),
		Tabs:                 toWireLayoutAuthoringStringListChange(changes.Tabs),
		Sections:             toWireLayoutAuthoringSectionListChange(changes.Sections),
		RelatedLists:         toWireLayoutAuthoringRelatedListListChange(changes.RelatedLists),
		RecordPanels:         toWireLayoutAuthoringRecordPanelListChange(changes.RecordPanels),
		HeaderActions:        toWireLayoutAuthoringActionPlacementChange(changes.HeaderActions),
		QuickActions:         toWireLayoutAuthoringActionPlacementChange(changes.QuickActions),
		RecordStates:         toWireLayoutAuthoringRecordStateRuleListChange(changes.RecordStates),
		PrimaryHeaderActions: toWireLayoutAuthoringStringListChange(changes.PrimaryHeaderActions),
	}
}

func fromWireLayoutAuthoringChanges(changes *runtimev1.LayoutAuthoringDocumentChanges) (semantic.LayoutDocumentChanges, error) {
	if changes == nil {
		return semantic.LayoutDocumentChanges{}, invalidPlatformWire()
	}
	var result semantic.LayoutDocumentChanges
	var err error
	if result.Name, err = fromWireLayoutAuthoringStringChange(changes.GetName()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.Kind, err = fromWireLayoutAuthoringStringChange(changes.GetKind()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.LayoutVersion, err = fromWireLayoutAuthoringUint32Change(changes.GetLayoutVersion()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.CompactFields, err = fromWireLayoutAuthoringStringListChange(changes.GetCompactFields()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.Tabs, err = fromWireLayoutAuthoringStringListChange(changes.GetTabs()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.Sections, err = fromWireLayoutAuthoringSectionListChange(changes.GetSections()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.RelatedLists, err = fromWireLayoutAuthoringRelatedListListChange(changes.GetRelatedLists()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.RecordPanels, err = fromWireLayoutAuthoringRecordPanelListChange(changes.GetRecordPanels()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.HeaderActions, err = fromWireLayoutAuthoringActionPlacementChange(changes.GetHeaderActions()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.QuickActions, err = fromWireLayoutAuthoringActionPlacementChange(changes.GetQuickActions()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.RecordStates, err = fromWireLayoutAuthoringRecordStateRuleListChange(changes.GetRecordStates()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	if result.PrimaryHeaderActions, err = fromWireLayoutAuthoringStringListChange(changes.GetPrimaryHeaderActions()); err != nil {
		return semantic.LayoutDocumentChanges{}, err
	}
	return result, nil
}

func toWireLayoutAuthoringChangeMode(mode semantic.ChangeMode) runtimev1.LayoutAuthoringChangeMode {
	switch mode {
	case semantic.ChangePreserve:
		return runtimev1.LayoutAuthoringChangeMode_LAYOUT_AUTHORING_CHANGE_MODE_PRESERVE
	case semantic.ChangeSet:
		return runtimev1.LayoutAuthoringChangeMode_LAYOUT_AUTHORING_CHANGE_MODE_SET
	case semantic.ChangeClear:
		return runtimev1.LayoutAuthoringChangeMode_LAYOUT_AUTHORING_CHANGE_MODE_CLEAR
	default:
		return runtimev1.LayoutAuthoringChangeMode_LAYOUT_AUTHORING_CHANGE_MODE_UNSPECIFIED
	}
}

func fromWireLayoutAuthoringChangeMode(mode runtimev1.LayoutAuthoringChangeMode) (semantic.ChangeMode, error) {
	switch mode {
	case runtimev1.LayoutAuthoringChangeMode_LAYOUT_AUTHORING_CHANGE_MODE_PRESERVE:
		return semantic.ChangePreserve, nil
	case runtimev1.LayoutAuthoringChangeMode_LAYOUT_AUTHORING_CHANGE_MODE_SET:
		return semantic.ChangeSet, nil
	case runtimev1.LayoutAuthoringChangeMode_LAYOUT_AUTHORING_CHANGE_MODE_CLEAR:
		return semantic.ChangeClear, nil
	default:
		return "", invalidPlatformWire()
	}
}

func toWireLayoutAuthoringStringChange(change semantic.Change[string]) *runtimev1.LayoutAuthoringStringChange {
	return &runtimev1.LayoutAuthoringStringChange{Mode: toWireLayoutAuthoringChangeMode(change.Mode), Value: cloneOptionalString(change.Value)}
}

func fromWireLayoutAuthoringStringChange(change *runtimev1.LayoutAuthoringStringChange) (semantic.Change[string], error) {
	if change == nil {
		return semantic.Change[string]{}, invalidPlatformWire()
	}
	mode, err := fromWireLayoutAuthoringChangeMode(change.GetMode())
	if err != nil {
		return semantic.Change[string]{}, err
	}
	return semantic.Change[string]{Mode: mode, Value: cloneOptionalString(change.Value)}, nil
}

func toWireLayoutAuthoringUint32Change(change semantic.Change[uint32]) *runtimev1.LayoutAuthoringUint32Change {
	var value *uint32
	if change.Value != nil {
		value = layoutAuthoringPointer(*change.Value)
	}
	return &runtimev1.LayoutAuthoringUint32Change{Mode: toWireLayoutAuthoringChangeMode(change.Mode), Value: value}
}

func fromWireLayoutAuthoringUint32Change(change *runtimev1.LayoutAuthoringUint32Change) (semantic.Change[uint32], error) {
	if change == nil {
		return semantic.Change[uint32]{}, invalidPlatformWire()
	}
	mode, err := fromWireLayoutAuthoringChangeMode(change.GetMode())
	if err != nil {
		return semantic.Change[uint32]{}, err
	}
	var value *uint32
	if change.Value != nil {
		value = layoutAuthoringPointer(change.GetValue())
	}
	return semantic.Change[uint32]{Mode: mode, Value: value}, nil
}

func toWireLayoutAuthoringStringListChange(change semantic.Change[[]string]) *runtimev1.LayoutAuthoringStringListChange {
	result := &runtimev1.LayoutAuthoringStringListChange{Mode: toWireLayoutAuthoringChangeMode(change.Mode)}
	if change.Value != nil {
		result.Value = &runtimev1.LayoutAuthoringStringList{Values: cloneStrings(*change.Value)}
	}
	return result
}

func fromWireLayoutAuthoringStringListChange(change *runtimev1.LayoutAuthoringStringListChange) (semantic.Change[[]string], error) {
	if change == nil {
		return semantic.Change[[]string]{}, invalidPlatformWire()
	}
	mode, err := fromWireLayoutAuthoringChangeMode(change.GetMode())
	if err != nil {
		return semantic.Change[[]string]{}, err
	}
	var value *[]string
	if change.Value != nil {
		mapped := cloneStrings(change.Value.GetValues())
		value = &mapped
	}
	return semantic.Change[[]string]{Mode: mode, Value: value}, nil
}

func toWireLayoutAuthoringSectionListChange(change semantic.Change[[]semantic.LayoutSection]) *runtimev1.LayoutAuthoringSectionListChange {
	result := &runtimev1.LayoutAuthoringSectionListChange{Mode: toWireLayoutAuthoringChangeMode(change.Mode)}
	if change.Value != nil {
		values := make([]*runtimev1.LayoutAuthoringSection, 0, len(*change.Value))
		for _, value := range *change.Value {
			values = append(values, toWireLayoutAuthoringSection(value))
		}
		result.Value = &runtimev1.LayoutAuthoringSectionList{Values: values}
	}
	return result
}

func fromWireLayoutAuthoringSectionListChange(change *runtimev1.LayoutAuthoringSectionListChange) (semantic.Change[[]semantic.LayoutSection], error) {
	if change == nil {
		return semantic.Change[[]semantic.LayoutSection]{}, invalidPlatformWire()
	}
	mode, err := fromWireLayoutAuthoringChangeMode(change.GetMode())
	if err != nil {
		return semantic.Change[[]semantic.LayoutSection]{}, err
	}
	var value *[]semantic.LayoutSection
	if change.Value != nil {
		values := make([]semantic.LayoutSection, 0, len(change.Value.GetValues()))
		for _, item := range change.Value.GetValues() {
			mapped, err := fromWireLayoutAuthoringSection(item)
			if err != nil {
				return semantic.Change[[]semantic.LayoutSection]{}, err
			}
			values = append(values, mapped)
		}
		value = &values
	}
	return semantic.Change[[]semantic.LayoutSection]{Mode: mode, Value: value}, nil
}

func toWireLayoutAuthoringRelatedListListChange(change semantic.Change[[]semantic.RelatedList]) *runtimev1.LayoutAuthoringRelatedListListChange {
	result := &runtimev1.LayoutAuthoringRelatedListListChange{Mode: toWireLayoutAuthoringChangeMode(change.Mode)}
	if change.Value != nil {
		values := make([]*runtimev1.LayoutAuthoringRelatedList, 0, len(*change.Value))
		for _, value := range *change.Value {
			values = append(values, toWireLayoutAuthoringRelatedList(value))
		}
		result.Value = &runtimev1.LayoutAuthoringRelatedListList{Values: values}
	}
	return result
}

func fromWireLayoutAuthoringRelatedListListChange(change *runtimev1.LayoutAuthoringRelatedListListChange) (semantic.Change[[]semantic.RelatedList], error) {
	if change == nil {
		return semantic.Change[[]semantic.RelatedList]{}, invalidPlatformWire()
	}
	mode, err := fromWireLayoutAuthoringChangeMode(change.GetMode())
	if err != nil {
		return semantic.Change[[]semantic.RelatedList]{}, err
	}
	var value *[]semantic.RelatedList
	if change.Value != nil {
		values := make([]semantic.RelatedList, 0, len(change.Value.GetValues()))
		for _, item := range change.Value.GetValues() {
			mapped, err := fromWireLayoutAuthoringRelatedList(item)
			if err != nil {
				return semantic.Change[[]semantic.RelatedList]{}, err
			}
			values = append(values, mapped)
		}
		value = &values
	}
	return semantic.Change[[]semantic.RelatedList]{Mode: mode, Value: value}, nil
}

func toWireLayoutAuthoringRecordPanelListChange(change semantic.Change[[]semantic.RecordPanel]) *runtimev1.LayoutAuthoringRecordPanelListChange {
	result := &runtimev1.LayoutAuthoringRecordPanelListChange{Mode: toWireLayoutAuthoringChangeMode(change.Mode)}
	if change.Value != nil {
		values := make([]*runtimev1.LayoutAuthoringRecordPanel, 0, len(*change.Value))
		for _, value := range *change.Value {
			values = append(values, toWireLayoutAuthoringRecordPanel(value))
		}
		result.Value = &runtimev1.LayoutAuthoringRecordPanelList{Values: values}
	}
	return result
}

func fromWireLayoutAuthoringRecordPanelListChange(change *runtimev1.LayoutAuthoringRecordPanelListChange) (semantic.Change[[]semantic.RecordPanel], error) {
	if change == nil {
		return semantic.Change[[]semantic.RecordPanel]{}, invalidPlatformWire()
	}
	mode, err := fromWireLayoutAuthoringChangeMode(change.GetMode())
	if err != nil {
		return semantic.Change[[]semantic.RecordPanel]{}, err
	}
	var value *[]semantic.RecordPanel
	if change.Value != nil {
		values := make([]semantic.RecordPanel, 0, len(change.Value.GetValues()))
		for _, item := range change.Value.GetValues() {
			mapped, err := fromWireLayoutAuthoringRecordPanel(item)
			if err != nil {
				return semantic.Change[[]semantic.RecordPanel]{}, err
			}
			values = append(values, mapped)
		}
		value = &values
	}
	return semantic.Change[[]semantic.RecordPanel]{Mode: mode, Value: value}, nil
}

func toWireLayoutAuthoringActionPlacementChange(change semantic.Change[semantic.ActionPlacement]) *runtimev1.LayoutAuthoringActionPlacementChange {
	result := &runtimev1.LayoutAuthoringActionPlacementChange{Mode: toWireLayoutAuthoringChangeMode(change.Mode)}
	if change.Value != nil {
		result.Value = toWireLayoutAuthoringActionPlacement(*change.Value)
	}
	return result
}

func fromWireLayoutAuthoringActionPlacementChange(change *runtimev1.LayoutAuthoringActionPlacementChange) (semantic.Change[semantic.ActionPlacement], error) {
	if change == nil {
		return semantic.Change[semantic.ActionPlacement]{}, invalidPlatformWire()
	}
	mode, err := fromWireLayoutAuthoringChangeMode(change.GetMode())
	if err != nil {
		return semantic.Change[semantic.ActionPlacement]{}, err
	}
	var value *semantic.ActionPlacement
	if change.Value != nil {
		mapped, err := fromWireLayoutAuthoringActionPlacement(change.Value)
		if err != nil {
			return semantic.Change[semantic.ActionPlacement]{}, err
		}
		value = &mapped
	}
	return semantic.Change[semantic.ActionPlacement]{Mode: mode, Value: value}, nil
}

func toWireLayoutAuthoringRecordStateRuleListChange(change semantic.Change[[]semantic.RecordStateRule]) *runtimev1.LayoutAuthoringRecordStateRuleListChange {
	result := &runtimev1.LayoutAuthoringRecordStateRuleListChange{Mode: toWireLayoutAuthoringChangeMode(change.Mode)}
	if change.Value != nil {
		values := make([]*runtimev1.LayoutAuthoringRecordStateRule, 0, len(*change.Value))
		for _, value := range *change.Value {
			values = append(values, toWireLayoutAuthoringRecordStateRule(value))
		}
		result.Value = &runtimev1.LayoutAuthoringRecordStateRuleList{Values: values}
	}
	return result
}

func fromWireLayoutAuthoringRecordStateRuleListChange(change *runtimev1.LayoutAuthoringRecordStateRuleListChange) (semantic.Change[[]semantic.RecordStateRule], error) {
	if change == nil {
		return semantic.Change[[]semantic.RecordStateRule]{}, invalidPlatformWire()
	}
	mode, err := fromWireLayoutAuthoringChangeMode(change.GetMode())
	if err != nil {
		return semantic.Change[[]semantic.RecordStateRule]{}, err
	}
	var value *[]semantic.RecordStateRule
	if change.Value != nil {
		values := make([]semantic.RecordStateRule, 0, len(change.Value.GetValues()))
		for _, item := range change.Value.GetValues() {
			mapped, err := fromWireLayoutAuthoringRecordStateRule(item)
			if err != nil {
				return semantic.Change[[]semantic.RecordStateRule]{}, err
			}
			values = append(values, mapped)
		}
		value = &values
	}
	return semantic.Change[[]semantic.RecordStateRule]{Mode: mode, Value: value}, nil
}
