package mapping

import (
	"context"
	"errors"

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

var layoutAuthoringCapability = platformCapability(semantic.CapabilityName)

func requireLayoutAuthoringSemanticShape() error {
	return requirePlatformSemanticShape(semantic.CapabilityName)
}

func ToWireLayoutAuthoringSubmitRequest(ctx context.Context, request semantic.SubmitRequest) (*runtimev1.LayoutAuthoringServiceSubmitRequest, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return nil, err
	}
	if err := semantic.ValidateSubmitRequest(ctx, request); err != nil {
		return nil, err
	}
	result := &runtimev1.LayoutAuthoringServiceSubmitRequest{
		CommandId: request.CommandID, IdempotencyKey: request.IdempotencyKey,
		BaseCatalogRevision: request.BaseCatalogRevision, WaitMode: toWireLayoutAuthoringWaitMode(request.WaitMode),
	}
	switch {
	case request.Operation.Create != nil:
		result.Operation = &runtimev1.LayoutAuthoringServiceSubmitRequest_Create{Create: toWireLayoutAuthoringCreate(*request.Operation.Create)}
	case request.Operation.Update != nil:
		result.Operation = &runtimev1.LayoutAuthoringServiceSubmitRequest_Update{Update: toWireLayoutAuthoringUpdate(*request.Operation.Update)}
	case request.Operation.Clone != nil:
		value := request.Operation.Clone
		result.Operation = &runtimev1.LayoutAuthoringServiceSubmitRequest_Clone{Clone: &runtimev1.LayoutAuthoringCloneLayout{
			SourceLayoutId: value.SourceLayoutID, SourceResourceVersion: value.SourceResourceVersion,
			TargetLayoutId: value.TargetLayoutID, TargetName: value.TargetName, ExpectedWorkspaceVersion: value.ExpectedWorkspaceVersion,
		}}
	case request.Operation.SetDefault != nil:
		value := request.Operation.SetDefault
		result.Operation = &runtimev1.LayoutAuthoringServiceSubmitRequest_SetDefault{SetDefault: &runtimev1.LayoutAuthoringSetDefaultLayout{
			ObjectId: value.ObjectID, LayoutId: value.LayoutID, ExpectedWorkspaceVersion: value.ExpectedWorkspaceVersion,
		}}
	case request.Operation.Delete != nil:
		value := request.Operation.Delete
		result.Operation = &runtimev1.LayoutAuthoringServiceSubmitRequest_Delete{Delete: &runtimev1.LayoutAuthoringDeleteLayout{
			LayoutId: value.LayoutID, ExpectedResourceVersion: value.ExpectedResourceVersion, ExpectedWorkspaceVersion: value.ExpectedWorkspaceVersion,
		}}
	case request.Operation.Restore != nil:
		value := request.Operation.Restore
		result.Operation = &runtimev1.LayoutAuthoringServiceSubmitRequest_Restore{Restore: &runtimev1.LayoutAuthoringRestoreLayout{
			LayoutId: value.LayoutID, HistoryVersion: value.HistoryVersion, ExpectedResourceVersion: value.ExpectedResourceVersion,
		}}
	case request.Operation.AssignmentUpsert != nil:
		value := request.Operation.AssignmentUpsert
		result.Operation = &runtimev1.LayoutAuthoringServiceSubmitRequest_AssignmentUpsert{AssignmentUpsert: &runtimev1.LayoutAuthoringUpsertAssignment{
			ObjectId: value.ObjectID, LayoutId: value.LayoutID, Selectors: toWireLayoutAuthoringSelectors(value.Selectors),
			ExpectedWorkspaceVersion: value.ExpectedWorkspaceVersion,
		}}
	case request.Operation.AssignmentDelete != nil:
		value := request.Operation.AssignmentDelete
		result.Operation = &runtimev1.LayoutAuthoringServiceSubmitRequest_AssignmentDelete{AssignmentDelete: &runtimev1.LayoutAuthoringDeleteAssignment{
			AssignmentId: value.AssignmentID, ExpectedResourceVersion: value.ExpectedResourceVersion, ExpectedWorkspaceVersion: value.ExpectedWorkspaceVersion,
		}}
	}
	return result, nil
}

func FromWireLayoutAuthoringSubmitRequest(ctx context.Context, request *runtimev1.LayoutAuthoringServiceSubmitRequest) (semantic.SubmitRequest, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return semantic.SubmitRequest{}, err
	}
	if request == nil {
		return semantic.SubmitRequest{}, invalidPlatformWire()
	}
	if err := preflightWireLayoutAuthoringSubmitRequest(request); err != nil {
		return semantic.SubmitRequest{}, err
	}
	waitMode, err := fromWireLayoutAuthoringWaitMode(request.GetWaitMode())
	if err != nil {
		return semantic.SubmitRequest{}, err
	}
	result := semantic.SubmitRequest{
		CommandID: request.GetCommandId(), IdempotencyKey: request.GetIdempotencyKey(),
		BaseCatalogRevision: request.GetBaseCatalogRevision(), WaitMode: waitMode,
	}
	switch operation := request.Operation.(type) {
	case *runtimev1.LayoutAuthoringServiceSubmitRequest_Create:
		value, err := fromWireLayoutAuthoringCreate(operation.Create)
		if err != nil {
			return semantic.SubmitRequest{}, err
		}
		result.Operation.Create = &value
	case *runtimev1.LayoutAuthoringServiceSubmitRequest_Update:
		value, err := fromWireLayoutAuthoringUpdate(operation.Update)
		if err != nil {
			return semantic.SubmitRequest{}, err
		}
		result.Operation.Update = &value
	case *runtimev1.LayoutAuthoringServiceSubmitRequest_Clone:
		if operation.Clone == nil {
			return semantic.SubmitRequest{}, invalidPlatformWire()
		}
		result.Operation.Clone = &semantic.CloneLayout{
			SourceLayoutID: operation.Clone.GetSourceLayoutId(), SourceResourceVersion: operation.Clone.GetSourceResourceVersion(),
			TargetLayoutID: operation.Clone.GetTargetLayoutId(), TargetName: operation.Clone.GetTargetName(), ExpectedWorkspaceVersion: operation.Clone.GetExpectedWorkspaceVersion(),
		}
	case *runtimev1.LayoutAuthoringServiceSubmitRequest_SetDefault:
		if operation.SetDefault == nil {
			return semantic.SubmitRequest{}, invalidPlatformWire()
		}
		result.Operation.SetDefault = &semantic.SetDefaultLayout{ObjectID: operation.SetDefault.GetObjectId(), LayoutID: operation.SetDefault.GetLayoutId(), ExpectedWorkspaceVersion: operation.SetDefault.GetExpectedWorkspaceVersion()}
	case *runtimev1.LayoutAuthoringServiceSubmitRequest_Delete:
		if operation.Delete == nil {
			return semantic.SubmitRequest{}, invalidPlatformWire()
		}
		result.Operation.Delete = &semantic.DeleteLayout{LayoutID: operation.Delete.GetLayoutId(), ExpectedResourceVersion: operation.Delete.GetExpectedResourceVersion(), ExpectedWorkspaceVersion: operation.Delete.GetExpectedWorkspaceVersion()}
	case *runtimev1.LayoutAuthoringServiceSubmitRequest_Restore:
		if operation.Restore == nil {
			return semantic.SubmitRequest{}, invalidPlatformWire()
		}
		result.Operation.Restore = &semantic.RestoreLayout{LayoutID: operation.Restore.GetLayoutId(), HistoryVersion: operation.Restore.GetHistoryVersion(), ExpectedResourceVersion: operation.Restore.GetExpectedResourceVersion()}
	case *runtimev1.LayoutAuthoringServiceSubmitRequest_AssignmentUpsert:
		if operation.AssignmentUpsert == nil {
			return semantic.SubmitRequest{}, invalidPlatformWire()
		}
		selectors, err := fromWireLayoutAuthoringSelectors(operation.AssignmentUpsert.GetSelectors())
		if err != nil {
			return semantic.SubmitRequest{}, err
		}
		result.Operation.AssignmentUpsert = &semantic.UpsertLayoutAssignment{
			ObjectID: operation.AssignmentUpsert.GetObjectId(), LayoutID: operation.AssignmentUpsert.GetLayoutId(),
			Selectors: selectors, ExpectedWorkspaceVersion: operation.AssignmentUpsert.GetExpectedWorkspaceVersion(),
		}
	case *runtimev1.LayoutAuthoringServiceSubmitRequest_AssignmentDelete:
		if operation.AssignmentDelete == nil {
			return semantic.SubmitRequest{}, invalidPlatformWire()
		}
		result.Operation.AssignmentDelete = &semantic.DeleteLayoutAssignment{
			AssignmentID: operation.AssignmentDelete.GetAssignmentId(), ExpectedResourceVersion: operation.AssignmentDelete.GetExpectedResourceVersion(),
			ExpectedWorkspaceVersion: operation.AssignmentDelete.GetExpectedWorkspaceVersion(),
		}
	default:
		return semantic.SubmitRequest{}, invalidPlatformWire()
	}
	if err := semantic.ValidateSubmitRequest(ctx, result); err != nil {
		return semantic.SubmitRequest{}, err
	}
	return result, nil
}

func ToWireLayoutAuthoringSubmitResponse(request semantic.SubmitRequest, response semantic.SubmitResponse) (*runtimev1.LayoutAuthoringServiceSubmitResponse, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return nil, err
	}
	if err := semantic.ValidateSubmitResponse(request, response); err != nil {
		return nil, err
	}
	return &runtimev1.LayoutAuthoringServiceSubmitResponse{Duplicate: response.Duplicate, Command: toWireLayoutAuthoringStatus(response.Command)}, nil
}

func FromWireLayoutAuthoringSubmitResponse(request semantic.SubmitRequest, response *runtimev1.LayoutAuthoringServiceSubmitResponse) (semantic.SubmitResponse, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return semantic.SubmitResponse{}, err
	}
	if response == nil {
		return semantic.SubmitResponse{}, incompatibleFailureFor(layoutAuthoringCapability)
	}
	if err := preflightWireLayoutAuthoringSubmitResponse(response); err != nil {
		return semantic.SubmitResponse{}, layoutAuthoringResponseError(err)
	}
	command, err := fromWireLayoutAuthoringStatus(response.GetCommand())
	if err != nil {
		return semantic.SubmitResponse{}, layoutAuthoringResponseError(err)
	}
	result := semantic.SubmitResponse{Duplicate: response.GetDuplicate(), Command: command}
	if err := semantic.ValidateSubmitResponse(request, result); err != nil {
		return semantic.SubmitResponse{}, err
	}
	return result, nil
}

func ToWireLayoutAuthoringGetCommandRequest(ctx context.Context, request semantic.GetCommandRequest) (*runtimev1.LayoutAuthoringServiceGetCommandRequest, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return nil, err
	}
	if err := semantic.ValidateGetCommandRequest(ctx, request); err != nil {
		return nil, err
	}
	return &runtimev1.LayoutAuthoringServiceGetCommandRequest{CommandId: request.CommandID, RequestDigest: request.RequestDigest}, nil
}

func FromWireLayoutAuthoringGetCommandRequest(ctx context.Context, request *runtimev1.LayoutAuthoringServiceGetCommandRequest) (semantic.GetCommandRequest, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return semantic.GetCommandRequest{}, err
	}
	if request == nil {
		return semantic.GetCommandRequest{}, invalidPlatformWire()
	}
	result := semantic.GetCommandRequest{CommandID: request.GetCommandId(), RequestDigest: request.GetRequestDigest()}
	if err := semantic.ValidateGetCommandRequest(ctx, result); err != nil {
		return semantic.GetCommandRequest{}, err
	}
	return result, nil
}

func ToWireLayoutAuthoringCommandStatus(request semantic.GetCommandRequest, response semantic.CommandStatus) (*runtimev1.LayoutAuthoringServiceGetCommandResponse, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return nil, err
	}
	if err := semantic.ValidateCommandStatus(request, response); err != nil {
		return nil, err
	}
	return toWireLayoutAuthoringStatus(response), nil
}

func FromWireLayoutAuthoringCommandStatus(request semantic.GetCommandRequest, response *runtimev1.LayoutAuthoringServiceGetCommandResponse) (semantic.CommandStatus, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return semantic.CommandStatus{}, err
	}
	if err := preflightWireLayoutAuthoringCommandStatus(response); err != nil {
		return semantic.CommandStatus{}, layoutAuthoringResponseError(err)
	}
	result, err := fromWireLayoutAuthoringStatus(response)
	if err != nil {
		return semantic.CommandStatus{}, layoutAuthoringResponseError(err)
	}
	if err := semantic.ValidateCommandStatus(request, result); err != nil {
		return semantic.CommandStatus{}, err
	}
	return result, nil
}

func ToWireLayoutAuthoringWorkspaceRequest(ctx context.Context, request semantic.WorkspaceRequest) (*runtimev1.LayoutAuthoringServiceReadWorkspaceRequest, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return nil, err
	}
	if err := semantic.ValidateWorkspaceRequest(ctx, request); err != nil {
		return nil, err
	}
	return &runtimev1.LayoutAuthoringServiceReadWorkspaceRequest{ObjectId: request.ObjectID, ViewRef: toWireLayoutAuthoringOptionalViewRef(request.ViewRef)}, nil
}

func FromWireLayoutAuthoringWorkspaceRequest(ctx context.Context, request *runtimev1.LayoutAuthoringServiceReadWorkspaceRequest) (semantic.WorkspaceRequest, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return semantic.WorkspaceRequest{}, err
	}
	if request == nil {
		return semantic.WorkspaceRequest{}, invalidPlatformWire()
	}
	result := semantic.WorkspaceRequest{ObjectID: request.GetObjectId(), ViewRef: fromWireLayoutAuthoringOptionalViewRef(request.ViewRef)}
	if err := semantic.ValidateWorkspaceRequest(ctx, result); err != nil {
		return semantic.WorkspaceRequest{}, err
	}
	return result, nil
}

func ToWireLayoutAuthoringWorkspace(request semantic.WorkspaceRequest, response semantic.Workspace) (*runtimev1.LayoutAuthoringServiceReadWorkspaceResponse, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return nil, err
	}
	if err := semantic.ValidateWorkspaceResponse(request, response); err != nil {
		return nil, err
	}
	layouts := make([]*runtimev1.LayoutAuthoringLayoutSummary, 0, len(response.Layouts))
	for _, layout := range response.Layouts {
		layouts = append(layouts, toWireLayoutAuthoringLayoutSummary(layout))
	}
	assignments := make([]*runtimev1.LayoutAuthoringAssignmentSummary, 0, len(response.Assignments))
	for _, assignment := range response.Assignments {
		assignments = append(assignments, toWireLayoutAuthoringAssignmentSummary(assignment))
	}
	return &runtimev1.LayoutAuthoringServiceReadWorkspaceResponse{
		ObjectId: response.ObjectID, WorkspaceVersion: response.WorkspaceVersion, Layouts: layouts, Assignments: assignments,
		ViewRef: toWireLayoutAuthoringViewRef(response.ViewRef), Receipts: toWireReceipts(response.Receipts, layoutAuthoringCapability),
	}, nil
}

func FromWireLayoutAuthoringWorkspace(request semantic.WorkspaceRequest, response *runtimev1.LayoutAuthoringServiceReadWorkspaceResponse) (semantic.Workspace, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return semantic.Workspace{}, err
	}
	if response == nil || response.GetViewRef() == nil || response.GetReceipts() == nil {
		return semantic.Workspace{}, incompatibleFailureFor(layoutAuthoringCapability)
	}
	if err := preflightWireLayoutAuthoringWorkspace(response); err != nil {
		return semantic.Workspace{}, layoutAuthoringResponseError(err)
	}
	receipts, err := fromWireReceipts(response.GetReceipts(), layoutAuthoringCapability)
	if err != nil {
		return semantic.Workspace{}, layoutAuthoringResponseError(err)
	}
	result := semantic.Workspace{
		ObjectID: response.GetObjectId(), WorkspaceVersion: response.GetWorkspaceVersion(),
		Layouts:     make([]semantic.LayoutSummary, 0, len(response.GetLayouts())),
		Assignments: make([]semantic.LayoutAssignmentSummary, 0, len(response.GetAssignments())),
		ViewRef:     fromWireLayoutAuthoringViewRef(response.GetViewRef()), Receipts: receipts,
	}
	for _, layout := range response.GetLayouts() {
		mapped, err := fromWireLayoutAuthoringLayoutSummary(layout)
		if err != nil {
			return semantic.Workspace{}, layoutAuthoringResponseError(err)
		}
		result.Layouts = append(result.Layouts, mapped)
	}
	for _, assignment := range response.GetAssignments() {
		mapped, err := fromWireLayoutAuthoringAssignmentSummary(assignment)
		if err != nil {
			return semantic.Workspace{}, layoutAuthoringResponseError(err)
		}
		result.Assignments = append(result.Assignments, mapped)
	}
	if err := semantic.ValidateWorkspaceResponse(request, result); err != nil {
		return semantic.Workspace{}, err
	}
	return result, nil
}

func ToWireLayoutAuthoringStoredLayoutRequest(ctx context.Context, request semantic.StoredLayoutRequest) (*runtimev1.LayoutAuthoringServiceReadStoredLayoutRequest, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return nil, err
	}
	if err := semantic.ValidateStoredLayoutRequest(ctx, request); err != nil {
		return nil, err
	}
	return &runtimev1.LayoutAuthoringServiceReadStoredLayoutRequest{LayoutId: request.LayoutID, ViewRef: toWireLayoutAuthoringOptionalViewRef(request.ViewRef)}, nil
}

func FromWireLayoutAuthoringStoredLayoutRequest(ctx context.Context, request *runtimev1.LayoutAuthoringServiceReadStoredLayoutRequest) (semantic.StoredLayoutRequest, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return semantic.StoredLayoutRequest{}, err
	}
	if request == nil {
		return semantic.StoredLayoutRequest{}, invalidPlatformWire()
	}
	result := semantic.StoredLayoutRequest{LayoutID: request.GetLayoutId(), ViewRef: fromWireLayoutAuthoringOptionalViewRef(request.ViewRef)}
	if err := semantic.ValidateStoredLayoutRequest(ctx, result); err != nil {
		return semantic.StoredLayoutRequest{}, err
	}
	return result, nil
}

func ToWireLayoutAuthoringStoredLayout(request semantic.StoredLayoutRequest, response semantic.StoredLayout) (*runtimev1.LayoutAuthoringServiceReadStoredLayoutResponse, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return nil, err
	}
	if err := semantic.ValidateStoredLayoutResponse(request, response); err != nil {
		return nil, err
	}
	return &runtimev1.LayoutAuthoringServiceReadStoredLayoutResponse{
		Document: toWireLayoutAuthoringDocument(response.Document), OrderedListFields: cloneStrings(response.OrderedListFields),
		Lifecycle: &runtimev1.LayoutAuthoringLifecycleState{
			ProvenanceKind: response.Lifecycle.ProvenanceKind, GenerationVersion: response.Lifecycle.GenerationVersion,
			Customized: response.Lifecycle.Customized, IsDefault: response.Lifecycle.IsDefault,
			CreatedAt: response.Lifecycle.CreatedAt, LastModifiedAt: response.Lifecycle.LastModifiedAt,
		},
		ResourceVersion: response.ResourceVersion, AggregateVersion: response.AggregateVersion, WorkspaceVersion: response.WorkspaceVersion,
		CreateContext: toWireLayoutAuthoringCreateContext(response.CreateContext),
		ViewRef:       toWireLayoutAuthoringViewRef(response.ViewRef), Receipts: toWireReceipts(response.Receipts, layoutAuthoringCapability),
	}, nil
}

func FromWireLayoutAuthoringStoredLayout(request semantic.StoredLayoutRequest, response *runtimev1.LayoutAuthoringServiceReadStoredLayoutResponse) (semantic.StoredLayout, error) {
	if err := requireLayoutAuthoringSemanticShape(); err != nil {
		return semantic.StoredLayout{}, err
	}
	if response == nil || response.GetLifecycle() == nil || response.GetViewRef() == nil || response.GetReceipts() == nil {
		return semantic.StoredLayout{}, incompatibleFailureFor(layoutAuthoringCapability)
	}
	if err := preflightWireLayoutAuthoringStoredLayout(response); err != nil {
		return semantic.StoredLayout{}, layoutAuthoringResponseError(err)
	}
	document, err := fromWireLayoutAuthoringDocument(response.GetDocument())
	if err != nil {
		return semantic.StoredLayout{}, layoutAuthoringResponseError(err)
	}
	receipts, err := fromWireReceipts(response.GetReceipts(), layoutAuthoringCapability)
	if err != nil {
		return semantic.StoredLayout{}, layoutAuthoringResponseError(err)
	}
	result := semantic.StoredLayout{
		Document: document, OrderedListFields: cloneStrings(response.GetOrderedListFields()),
		Lifecycle: semantic.LayoutLifecycleState{
			ProvenanceKind: response.Lifecycle.GetProvenanceKind(), GenerationVersion: response.Lifecycle.GetGenerationVersion(),
			Customized: response.Lifecycle.GetCustomized(), IsDefault: response.Lifecycle.GetIsDefault(),
			CreatedAt: response.Lifecycle.GetCreatedAt(), LastModifiedAt: response.Lifecycle.GetLastModifiedAt(),
		},
		ResourceVersion: response.GetResourceVersion(), AggregateVersion: response.GetAggregateVersion(), WorkspaceVersion: response.GetWorkspaceVersion(),
		CreateContext: fromWireLayoutAuthoringCreateContext(response.CreateContext),
		ViewRef:       fromWireLayoutAuthoringViewRef(response.GetViewRef()), Receipts: receipts,
	}
	if err := semantic.ValidateStoredLayoutResponse(request, result); err != nil {
		return semantic.StoredLayout{}, err
	}
	return result, nil
}

func toWireLayoutAuthoringCreate(value semantic.CreateLayout) *runtimev1.LayoutAuthoringCreateLayout {
	return &runtimev1.LayoutAuthoringCreateLayout{
		Document: toWireLayoutAuthoringDocument(value.Document), ListFields: toWireLayoutAuthoringStringListChange(value.ListFields),
		ExpectedWorkspaceVersion: cloneOptionalString(value.ExpectedWorkspaceVersion),
	}
}

func fromWireLayoutAuthoringCreate(value *runtimev1.LayoutAuthoringCreateLayout) (semantic.CreateLayout, error) {
	if value == nil {
		return semantic.CreateLayout{}, invalidPlatformWire()
	}
	document, err := fromWireLayoutAuthoringDocument(value.GetDocument())
	if err != nil {
		return semantic.CreateLayout{}, err
	}
	listFields, err := fromWireLayoutAuthoringStringListChange(value.GetListFields())
	if err != nil {
		return semantic.CreateLayout{}, err
	}
	return semantic.CreateLayout{Document: document, ListFields: listFields, ExpectedWorkspaceVersion: cloneOptionalString(value.ExpectedWorkspaceVersion)}, nil
}

func toWireLayoutAuthoringUpdate(value semantic.UpdateLayout) *runtimev1.LayoutAuthoringUpdateLayout {
	return &runtimev1.LayoutAuthoringUpdateLayout{
		LayoutId: value.LayoutID, ExpectedAggregateVersion: value.ExpectedAggregateVersion,
		Changes: toWireLayoutAuthoringChanges(value.Changes), ListFields: toWireLayoutAuthoringStringListChange(value.ListFields),
	}
}

func fromWireLayoutAuthoringUpdate(value *runtimev1.LayoutAuthoringUpdateLayout) (semantic.UpdateLayout, error) {
	if value == nil {
		return semantic.UpdateLayout{}, invalidPlatformWire()
	}
	changes, err := fromWireLayoutAuthoringChanges(value.GetChanges())
	if err != nil {
		return semantic.UpdateLayout{}, err
	}
	listFields, err := fromWireLayoutAuthoringStringListChange(value.GetListFields())
	if err != nil {
		return semantic.UpdateLayout{}, err
	}
	return semantic.UpdateLayout{LayoutID: value.GetLayoutId(), ExpectedAggregateVersion: value.GetExpectedAggregateVersion(), Changes: changes, ListFields: listFields}, nil
}

func toWireLayoutAuthoringWaitMode(mode semantic.WaitMode) runtimev1.LayoutAuthoringWaitMode {
	if mode == semantic.WaitForTerminal {
		return runtimev1.LayoutAuthoringWaitMode_LAYOUT_AUTHORING_WAIT_MODE_WAIT_FOR_TERMINAL
	}
	if mode == semantic.ReturnAfterAcceptance {
		return runtimev1.LayoutAuthoringWaitMode_LAYOUT_AUTHORING_WAIT_MODE_RETURN_AFTER_ACCEPTANCE
	}
	return runtimev1.LayoutAuthoringWaitMode_LAYOUT_AUTHORING_WAIT_MODE_UNSPECIFIED
}

func fromWireLayoutAuthoringWaitMode(mode runtimev1.LayoutAuthoringWaitMode) (semantic.WaitMode, error) {
	switch mode {
	case runtimev1.LayoutAuthoringWaitMode_LAYOUT_AUTHORING_WAIT_MODE_WAIT_FOR_TERMINAL:
		return semantic.WaitForTerminal, nil
	case runtimev1.LayoutAuthoringWaitMode_LAYOUT_AUTHORING_WAIT_MODE_RETURN_AFTER_ACCEPTANCE:
		return semantic.ReturnAfterAcceptance, nil
	default:
		return "", invalidPlatformWire()
	}
}

func toWireLayoutAuthoringSelectors(selectors semantic.AssignmentSelectors) *runtimev1.LayoutAuthoringAssignmentSelectors {
	return &runtimev1.LayoutAuthoringAssignmentSelectors{
		ProfileId: cloneOptionalString(selectors.ProfileID), RoleId: cloneOptionalString(selectors.RoleID), RecordTypeId: cloneOptionalString(selectors.RecordTypeID),
	}
}

func fromWireLayoutAuthoringSelectors(selectors *runtimev1.LayoutAuthoringAssignmentSelectors) (semantic.AssignmentSelectors, error) {
	if selectors == nil {
		return semantic.AssignmentSelectors{}, invalidPlatformWire()
	}
	return semantic.AssignmentSelectors{
		ProfileID: cloneOptionalString(selectors.ProfileId), RoleID: cloneOptionalString(selectors.RoleId), RecordTypeID: cloneOptionalString(selectors.RecordTypeId),
	}, nil
}

func toWireLayoutAuthoringViewRef(ref semantic.CatalogViewRef) *runtimev1.LayoutAuthoringCatalogViewRef {
	return &runtimev1.LayoutAuthoringCatalogViewRef{CatalogRevision: ref.CatalogRevision, AuthoringViewDigest: ref.AuthoringViewDigest}
}

func toWireLayoutAuthoringOptionalViewRef(ref *semantic.CatalogViewRef) *runtimev1.LayoutAuthoringCatalogViewRef {
	if ref == nil {
		return nil
	}
	return toWireLayoutAuthoringViewRef(*ref)
}

func fromWireLayoutAuthoringViewRef(ref *runtimev1.LayoutAuthoringCatalogViewRef) semantic.CatalogViewRef {
	return semantic.CatalogViewRef{CatalogRevision: ref.GetCatalogRevision(), AuthoringViewDigest: ref.GetAuthoringViewDigest()}
}

func fromWireLayoutAuthoringOptionalViewRef(ref *runtimev1.LayoutAuthoringCatalogViewRef) *semantic.CatalogViewRef {
	if ref == nil {
		return nil
	}
	return layoutAuthoringPointer(fromWireLayoutAuthoringViewRef(ref))
}

func toWireLayoutAuthoringStatus(status semantic.CommandStatus) *runtimev1.LayoutAuthoringServiceGetCommandResponse {
	result := &runtimev1.LayoutAuthoringServiceGetCommandResponse{
		CommandId: status.CommandID, RequestDigest: status.RequestDigest, State: toWireLayoutAuthoringCommandState(status.State),
		CatalogViewRef: toWireLayoutAuthoringOptionalViewRef(status.CatalogViewRef), Receipts: toWireReceipts(status.Receipts, layoutAuthoringCapability),
	}
	if status.Failure != nil {
		result.Failure = &runtimev1.LayoutAuthoringCommandFailure{
			Category:       toWireLayoutAuthoringCommandFailureCategory(status.Failure.Category),
			Message:        status.Failure.Message,
			FieldReference: status.Failure.FieldReference,
		}
	}
	if status.Result != nil {
		semanticResult := status.Result
		switch {
		case semanticResult.Create != nil:
			result.Result = &runtimev1.LayoutAuthoringServiceGetCommandResponse_Create{Create: &runtimev1.LayoutAuthoringCreateLayoutResult{Layout: toWireLayoutAuthoringSnapshot(semanticResult.Create.Layout)}}
		case semanticResult.Update != nil:
			result.Result = &runtimev1.LayoutAuthoringServiceGetCommandResponse_Update{Update: &runtimev1.LayoutAuthoringUpdateLayoutResult{Layout: toWireLayoutAuthoringSnapshot(semanticResult.Update.Layout)}}
		case semanticResult.Clone != nil:
			result.Result = &runtimev1.LayoutAuthoringServiceGetCommandResponse_Clone{Clone: &runtimev1.LayoutAuthoringCloneLayoutResult{Layout: toWireLayoutAuthoringSnapshot(semanticResult.Clone.Layout)}}
		case semanticResult.SetDefault != nil:
			value := semanticResult.SetDefault
			result.Result = &runtimev1.LayoutAuthoringServiceGetCommandResponse_SetDefault{SetDefault: &runtimev1.LayoutAuthoringSetDefaultLayoutResult{ObjectId: value.ObjectID, LayoutId: value.LayoutID, WorkspaceVersion: value.WorkspaceVersion}}
		case semanticResult.Delete != nil:
			value := semanticResult.Delete
			result.Result = &runtimev1.LayoutAuthoringServiceGetCommandResponse_Delete{Delete: &runtimev1.LayoutAuthoringDeleteLayoutResult{LayoutId: value.LayoutID, ObjectId: value.ObjectID, WorkspaceVersion: value.WorkspaceVersion}}
		case semanticResult.Restore != nil:
			value := semanticResult.Restore
			result.Result = &runtimev1.LayoutAuthoringServiceGetCommandResponse_Restore{Restore: &runtimev1.LayoutAuthoringRestoreLayoutResult{Layout: toWireLayoutAuthoringSnapshot(value.Layout), HistoryVersion: value.HistoryVersion}}
		case semanticResult.AssignmentUpsert != nil:
			value := semanticResult.AssignmentUpsert
			result.Result = &runtimev1.LayoutAuthoringServiceGetCommandResponse_AssignmentUpsert{AssignmentUpsert: &runtimev1.LayoutAuthoringUpsertAssignmentResult{Assignment: toWireLayoutAuthoringAssignmentSummary(value.Assignment), WorkspaceVersion: value.WorkspaceVersion}}
		case semanticResult.AssignmentDelete != nil:
			value := semanticResult.AssignmentDelete
			result.Result = &runtimev1.LayoutAuthoringServiceGetCommandResponse_AssignmentDelete{AssignmentDelete: &runtimev1.LayoutAuthoringDeleteAssignmentResult{AssignmentId: value.AssignmentID, ObjectId: value.ObjectID, WorkspaceVersion: value.WorkspaceVersion}}
		}
	}
	return result
}

func fromWireLayoutAuthoringStatus(status *runtimev1.LayoutAuthoringServiceGetCommandResponse) (semantic.CommandStatus, error) {
	if status == nil || status.GetReceipts() == nil {
		return semantic.CommandStatus{}, incompatibleFailureFor(layoutAuthoringCapability)
	}
	state, err := fromWireLayoutAuthoringCommandState(status.GetState())
	if err != nil {
		return semantic.CommandStatus{}, err
	}
	receipts, err := fromWireReceipts(status.GetReceipts(), layoutAuthoringCapability)
	if err != nil {
		return semantic.CommandStatus{}, err
	}
	result := semantic.CommandStatus{
		CommandID: status.GetCommandId(), RequestDigest: status.GetRequestDigest(), State: state,
		CatalogViewRef: fromWireLayoutAuthoringOptionalViewRef(status.CatalogViewRef), Receipts: receipts,
	}
	if status.Failure != nil {
		category, err := fromWireLayoutAuthoringCommandFailureCategory(status.Failure.GetCategory())
		if err != nil {
			return semantic.CommandStatus{}, err
		}
		result.Failure = &semantic.CommandFailure{
			Category:       category,
			Message:        status.Failure.GetMessage(),
			FieldReference: status.Failure.GetFieldReference(),
		}
	}
	if status.Result != nil {
		mapped, err := fromWireLayoutAuthoringResult(status)
		if err != nil {
			return semantic.CommandStatus{}, err
		}
		result.Result = &mapped
	}
	return result, nil
}

func toWireLayoutAuthoringCommandFailureCategory(category semantic.FailureCategory) runtimev1.LayoutAuthoringCommandFailureCategory {
	switch category {
	case semantic.FailureInvalidRequest:
		return runtimev1.LayoutAuthoringCommandFailureCategory_LAYOUT_AUTHORING_COMMAND_FAILURE_CATEGORY_INVALID_REQUEST
	case semantic.FailureForbidden:
		return runtimev1.LayoutAuthoringCommandFailureCategory_LAYOUT_AUTHORING_COMMAND_FAILURE_CATEGORY_FORBIDDEN
	case semantic.FailureMissing:
		return runtimev1.LayoutAuthoringCommandFailureCategory_LAYOUT_AUTHORING_COMMAND_FAILURE_CATEGORY_MISSING
	case semantic.FailureConflict:
		return runtimev1.LayoutAuthoringCommandFailureCategory_LAYOUT_AUTHORING_COMMAND_FAILURE_CATEGORY_CONFLICT
	default:
		return runtimev1.LayoutAuthoringCommandFailureCategory_LAYOUT_AUTHORING_COMMAND_FAILURE_CATEGORY_UNSPECIFIED
	}
}

func fromWireLayoutAuthoringCommandFailureCategory(category runtimev1.LayoutAuthoringCommandFailureCategory) (semantic.FailureCategory, error) {
	switch category {
	case runtimev1.LayoutAuthoringCommandFailureCategory_LAYOUT_AUTHORING_COMMAND_FAILURE_CATEGORY_INVALID_REQUEST:
		return semantic.FailureInvalidRequest, nil
	case runtimev1.LayoutAuthoringCommandFailureCategory_LAYOUT_AUTHORING_COMMAND_FAILURE_CATEGORY_FORBIDDEN:
		return semantic.FailureForbidden, nil
	case runtimev1.LayoutAuthoringCommandFailureCategory_LAYOUT_AUTHORING_COMMAND_FAILURE_CATEGORY_MISSING:
		return semantic.FailureMissing, nil
	case runtimev1.LayoutAuthoringCommandFailureCategory_LAYOUT_AUTHORING_COMMAND_FAILURE_CATEGORY_CONFLICT:
		return semantic.FailureConflict, nil
	default:
		return "", incompatibleFailureFor(layoutAuthoringCapability)
	}
}

func toWireLayoutAuthoringCommandState(state semantic.CommandState) runtimev1.LayoutAuthoringCommandState {
	switch state {
	case semantic.StateAccepted:
		return runtimev1.LayoutAuthoringCommandState_LAYOUT_AUTHORING_COMMAND_STATE_ACCEPTED
	case semantic.StateInProgress:
		return runtimev1.LayoutAuthoringCommandState_LAYOUT_AUTHORING_COMMAND_STATE_IN_PROGRESS
	case semantic.StateSucceeded:
		return runtimev1.LayoutAuthoringCommandState_LAYOUT_AUTHORING_COMMAND_STATE_SUCCEEDED
	case semantic.StateFailed:
		return runtimev1.LayoutAuthoringCommandState_LAYOUT_AUTHORING_COMMAND_STATE_FAILED
	default:
		return runtimev1.LayoutAuthoringCommandState_LAYOUT_AUTHORING_COMMAND_STATE_UNSPECIFIED
	}
}

func fromWireLayoutAuthoringCommandState(state runtimev1.LayoutAuthoringCommandState) (semantic.CommandState, error) {
	switch state {
	case runtimev1.LayoutAuthoringCommandState_LAYOUT_AUTHORING_COMMAND_STATE_ACCEPTED:
		return semantic.StateAccepted, nil
	case runtimev1.LayoutAuthoringCommandState_LAYOUT_AUTHORING_COMMAND_STATE_IN_PROGRESS:
		return semantic.StateInProgress, nil
	case runtimev1.LayoutAuthoringCommandState_LAYOUT_AUTHORING_COMMAND_STATE_SUCCEEDED:
		return semantic.StateSucceeded, nil
	case runtimev1.LayoutAuthoringCommandState_LAYOUT_AUTHORING_COMMAND_STATE_FAILED:
		return semantic.StateFailed, nil
	default:
		return "", invalidPlatformWire()
	}
}

func fromWireLayoutAuthoringResult(status *runtimev1.LayoutAuthoringServiceGetCommandResponse) (semantic.CommandResult, error) {
	var result semantic.CommandResult
	switch value := status.Result.(type) {
	case *runtimev1.LayoutAuthoringServiceGetCommandResponse_Create:
		if value.Create == nil {
			return semantic.CommandResult{}, invalidPlatformWire()
		}
		layout, err := fromWireLayoutAuthoringSnapshot(value.Create.GetLayout())
		if err != nil {
			return semantic.CommandResult{}, err
		}
		result.Create = &semantic.CreateLayoutResult{Layout: layout}
	case *runtimev1.LayoutAuthoringServiceGetCommandResponse_Update:
		if value.Update == nil {
			return semantic.CommandResult{}, invalidPlatformWire()
		}
		layout, err := fromWireLayoutAuthoringSnapshot(value.Update.GetLayout())
		if err != nil {
			return semantic.CommandResult{}, err
		}
		result.Update = &semantic.UpdateLayoutResult{Layout: layout}
	case *runtimev1.LayoutAuthoringServiceGetCommandResponse_Clone:
		if value.Clone == nil {
			return semantic.CommandResult{}, invalidPlatformWire()
		}
		layout, err := fromWireLayoutAuthoringSnapshot(value.Clone.GetLayout())
		if err != nil {
			return semantic.CommandResult{}, err
		}
		result.Clone = &semantic.CloneLayoutResult{Layout: layout}
	case *runtimev1.LayoutAuthoringServiceGetCommandResponse_SetDefault:
		if value.SetDefault == nil {
			return semantic.CommandResult{}, invalidPlatformWire()
		}
		result.SetDefault = &semantic.SetDefaultLayoutResult{ObjectID: value.SetDefault.GetObjectId(), LayoutID: value.SetDefault.GetLayoutId(), WorkspaceVersion: value.SetDefault.GetWorkspaceVersion()}
	case *runtimev1.LayoutAuthoringServiceGetCommandResponse_Delete:
		if value.Delete == nil {
			return semantic.CommandResult{}, invalidPlatformWire()
		}
		result.Delete = &semantic.DeleteLayoutResult{LayoutID: value.Delete.GetLayoutId(), ObjectID: value.Delete.GetObjectId(), WorkspaceVersion: value.Delete.GetWorkspaceVersion()}
	case *runtimev1.LayoutAuthoringServiceGetCommandResponse_Restore:
		if value.Restore == nil {
			return semantic.CommandResult{}, invalidPlatformWire()
		}
		layout, err := fromWireLayoutAuthoringSnapshot(value.Restore.GetLayout())
		if err != nil {
			return semantic.CommandResult{}, err
		}
		result.Restore = &semantic.RestoreLayoutResult{Layout: layout, HistoryVersion: value.Restore.GetHistoryVersion()}
	case *runtimev1.LayoutAuthoringServiceGetCommandResponse_AssignmentUpsert:
		if value.AssignmentUpsert == nil {
			return semantic.CommandResult{}, invalidPlatformWire()
		}
		assignment, err := fromWireLayoutAuthoringAssignmentSummary(value.AssignmentUpsert.GetAssignment())
		if err != nil {
			return semantic.CommandResult{}, err
		}
		result.AssignmentUpsert = &semantic.UpsertLayoutAssignmentResult{Assignment: assignment, WorkspaceVersion: value.AssignmentUpsert.GetWorkspaceVersion()}
	case *runtimev1.LayoutAuthoringServiceGetCommandResponse_AssignmentDelete:
		if value.AssignmentDelete == nil {
			return semantic.CommandResult{}, invalidPlatformWire()
		}
		result.AssignmentDelete = &semantic.DeleteLayoutAssignmentResult{AssignmentID: value.AssignmentDelete.GetAssignmentId(), ObjectID: value.AssignmentDelete.GetObjectId(), WorkspaceVersion: value.AssignmentDelete.GetWorkspaceVersion()}
	default:
		return semantic.CommandResult{}, invalidPlatformWire()
	}
	return result, nil
}

func toWireLayoutAuthoringSnapshot(snapshot semantic.LayoutSnapshot) *runtimev1.LayoutAuthoringLayoutSnapshot {
	return &runtimev1.LayoutAuthoringLayoutSnapshot{
		Document: toWireLayoutAuthoringDocument(snapshot.Document), OrderedListFields: cloneStrings(snapshot.OrderedListFields),
		ResourceVersion: snapshot.ResourceVersion, AggregateVersion: snapshot.AggregateVersion, WorkspaceVersion: snapshot.WorkspaceVersion,
	}
}

func fromWireLayoutAuthoringSnapshot(snapshot *runtimev1.LayoutAuthoringLayoutSnapshot) (semantic.LayoutSnapshot, error) {
	if snapshot == nil {
		return semantic.LayoutSnapshot{}, invalidPlatformWire()
	}
	document, err := fromWireLayoutAuthoringDocument(snapshot.GetDocument())
	if err != nil {
		return semantic.LayoutSnapshot{}, err
	}
	return semantic.LayoutSnapshot{
		Document: document, OrderedListFields: cloneStrings(snapshot.GetOrderedListFields()),
		ResourceVersion: snapshot.GetResourceVersion(), AggregateVersion: snapshot.GetAggregateVersion(), WorkspaceVersion: snapshot.GetWorkspaceVersion(),
	}, nil
}

func toWireLayoutAuthoringLayoutSummary(layout semantic.LayoutSummary) *runtimev1.LayoutAuthoringLayoutSummary {
	return &runtimev1.LayoutAuthoringLayoutSummary{
		LayoutId: layout.LayoutID, ObjectId: layout.ObjectID, Name: layout.Name, Kind: layout.Kind,
		IsDefault: layout.IsDefault, ResourceVersion: layout.ResourceVersion, CreatedAt: layout.CreatedAt, LastModifiedAt: layout.LastModifiedAt,
	}
}

func fromWireLayoutAuthoringLayoutSummary(layout *runtimev1.LayoutAuthoringLayoutSummary) (semantic.LayoutSummary, error) {
	if layout == nil {
		return semantic.LayoutSummary{}, invalidPlatformWire()
	}
	return semantic.LayoutSummary{
		LayoutID: layout.GetLayoutId(), ObjectID: layout.GetObjectId(), Name: layout.GetName(), Kind: layout.GetKind(),
		IsDefault: layout.GetIsDefault(), ResourceVersion: layout.GetResourceVersion(), CreatedAt: layout.GetCreatedAt(), LastModifiedAt: layout.GetLastModifiedAt(),
	}, nil
}

func toWireLayoutAuthoringAssignmentSummary(assignment semantic.LayoutAssignmentSummary) *runtimev1.LayoutAuthoringAssignmentSummary {
	return &runtimev1.LayoutAuthoringAssignmentSummary{
		AssignmentId: assignment.AssignmentID, ObjectId: assignment.ObjectID, LayoutId: assignment.LayoutID,
		Selectors: toWireLayoutAuthoringSelectors(assignment.Selectors), Specificity: assignment.Specificity,
		ResourceVersion: assignment.ResourceVersion, CreatedAt: assignment.CreatedAt, LastModifiedAt: assignment.LastModifiedAt,
		CreatedById: cloneOptionalString(assignment.CreatedByID),
	}
}

func fromWireLayoutAuthoringAssignmentSummary(assignment *runtimev1.LayoutAuthoringAssignmentSummary) (semantic.LayoutAssignmentSummary, error) {
	if assignment == nil {
		return semantic.LayoutAssignmentSummary{}, invalidPlatformWire()
	}
	selectors, err := fromWireLayoutAuthoringSelectors(assignment.GetSelectors())
	if err != nil {
		return semantic.LayoutAssignmentSummary{}, err
	}
	return semantic.LayoutAssignmentSummary{
		AssignmentID: assignment.GetAssignmentId(), ObjectID: assignment.GetObjectId(), LayoutID: assignment.GetLayoutId(),
		Selectors: selectors, Specificity: assignment.GetSpecificity(), ResourceVersion: assignment.GetResourceVersion(),
		CreatedAt: assignment.GetCreatedAt(), LastModifiedAt: assignment.GetLastModifiedAt(), CreatedByID: cloneOptionalString(assignment.CreatedById),
	}, nil
}

func layoutAuthoringResponseError(err error) error {
	var failure *semantic.Failure
	if errors.As(err, &failure) && failure.Category == semantic.FailureInvalidRequest {
		return internalPlatformWire()
	}
	return err
}

func toWireLayoutAuthoringCreateContext(context *semantic.CreateContext) *runtimev1.LayoutAuthoringCreateContext {
	if context == nil {
		return nil
	}
	return &runtimev1.LayoutAuthoringCreateContext{RequiredFields: cloneStrings(context.RequiredFields)}
}

func fromWireLayoutAuthoringCreateContext(context *runtimev1.LayoutAuthoringCreateContext) *semantic.CreateContext {
	if context == nil {
		return nil
	}
	return &semantic.CreateContext{RequiredFields: cloneStrings(context.GetRequiredFields())}
}
