package keeper

import (
    "fmt"
	"context"

    "<%= ModulePath %>/x/<%= ModuleName %>/types"
    "cosmossdk.io/collections"
    errorsmod "cosmossdk.io/errors"
    sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)


func (k msgServer) Create<%= TypeName.PascalCase %>(ctx context.Context,  msg *types.MsgCreate<%= TypeName.PascalCase %>) (*types.MsgCreate<%= TypeName.PascalCase %>Response, error) {
    if _, err := k.addressCodec.StringToBytes(msg.<%= MsgSigner.UpperCamel %>); err != nil {
        return nil, errorsmod.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid address: %s", err))
    }

    // Check if the value already exists
    ok, err := k.<%= TypeName.UpperCamel %>.Has(ctx, msg.<%= Index.Name.UpperCamel %>)
    if err != nil {
        return nil, errorsmod.Wrap(sdkerrors.ErrLogic, err.Error())
    } else if ok {
        return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "index already set")
    }

    var <%= TypeName.LowerCamel %> = types.<%= TypeName.PascalCase %>{
        <%= MsgSigner.UpperCamel %>: msg.<%= MsgSigner.UpperCamel %>,
        <%= Index.Name.UpperCamel %>: msg.<%= Index.Name.UpperCamel %>,
        <%= for (field) in Fields { %><%= field.Name.UpperCamel %>: msg.<%= field.Name.UpperCamel %>,
        <% } %>
    }

    if err := k.<%= TypeName.UpperCamel %>.Set(ctx, <%= TypeName.LowerCamel %>.<%= Index.Name.UpperCamel %>, <%= TypeName.LowerCamel %>); err != nil {
        return nil, errorsmod.Wrap(sdkerrors.ErrLogic, err.Error())
    }

    return &types.MsgCreate<%= TypeName.PascalCase %>Response{}, nil
}

func (k msgServer) Update<%= TypeName.PascalCase %>(ctx context.Context,  msg *types.MsgUpdate<%= TypeName.PascalCase %>) (*types.MsgUpdate<%= TypeName.PascalCase %>Response, error) {
    if _, err := k.addressCodec.StringToBytes(msg.<%= MsgSigner.UpperCamel %>); err != nil {
        return nil, errorsmod.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid signer address: %s", err))
    }

    // Check if the value exists
    val, err := k.<%= TypeName.UpperCamel %>.Get(ctx, msg.<%= Index.Name.UpperCamel %>)
    if err != nil {
        if errors.Is(err, collections.ErrNotFound) {
            return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, "index not set")
        }

        return nil, errorsmod.Wrap(sdkerrors.ErrLogic, err.Error())
    }

    // Checks if the msg <%= MsgSigner.LowerCamel %> is the same as the current owner
    if msg.<%= MsgSigner.UpperCamel %> != val.<%= MsgSigner.UpperCamel %> {
        return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
    }

    var <%= TypeName.LowerCamel %> = types.<%= TypeName.PascalCase %>{
		<%= MsgSigner.UpperCamel %>: msg.<%= MsgSigner.UpperCamel %>,
		<%= Index.Name.UpperCamel %>: msg.<%= Index.Name.UpperCamel %>,
        <%= for (field) in Fields { %><%= field.Name.UpperCamel %>: msg.<%= field.Name.UpperCamel %>,
		<% } %>
	}

    if err := k.<%= TypeName.UpperCamel %>.Set(ctx, <%= TypeName.LowerCamel %>.<%= Index.Name.UpperCamel %>, <%= TypeName.LowerCamel %>); err != nil {
        return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "failed to update <%= TypeName.LowerCamel %>")
    }

	return &types.MsgUpdate<%= TypeName.PascalCase %>Response{}, nil
}

func (k msgServer) Delete<%= TypeName.PascalCase %>(ctx context.Context,  msg *types.MsgDelete<%= TypeName.PascalCase %>) (*types.MsgDelete<%= TypeName.PascalCase %>Response, error) {
    if _, err := k.addressCodec.StringToBytes(msg.<%= MsgSigner.UpperCamel %>); err != nil {
        return nil, errorsmod.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid signer address: %s", err))
    }

    // Check if the value exists
    val, err := k.<%= TypeName.UpperCamel %>.Get(ctx, msg.<%= Index.Name.UpperCamel %>)
    if err != nil {
        if errors.Is(err, collections.ErrNotFound) {
            return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, "index not set")
        }

        return nil, errorsmod.Wrap(sdkerrors.ErrLogic, err.Error())
    }

    // Checks if the msg <%= MsgSigner.LowerCamel %> is the same as the current owner
    if msg.<%= MsgSigner.UpperCamel %> != val.<%= MsgSigner.UpperCamel %> {
        return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
    }

	if err := k.<%= TypeName.UpperCamel %>.Remove(ctx, msg.<%= Index.Name.UpperCamel %>); err != nil {
        return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "failed to remove <%= TypeName.LowerCamel %>")
    }

	return &types.MsgDelete<%= TypeName.PascalCase %>Response{}, nil
}
