// Generated by Ignite ignite.com/cli

import { SigningStargateClient, DeliverTxResponse, StdFee } from "@cosmjs/stargate";
import { EncodeObject, GeneratedType, OfflineSigner, Registry } from "@cosmjs/proto-signing";
import { msgTypes } from './registry';
import { IgniteClient } from "../client"
import { MissingWalletError } from "../helpers"
import { Api } from "./rest";
import { MsgMyMessageRequest } from "./types/ignite/planet/mars/mars";
import { MsgBarRequest } from "./types/ignite/planet/mars/mars";

import { AnotherType as typeAnotherType} from "./types"

export { MsgMyMessageRequest, MsgBarRequest };

type sendMsgMyMessageRequestParams = {
  value: MsgMyMessageRequest,
  fee?: StdFee,
  memo?: string
};

type sendMsgBarRequestParams = {
  value: MsgBarRequest,
  fee?: StdFee,
  memo?: string
};


type msgMyMessageRequestParams = {
  value: MsgMyMessageRequest,
};

type msgBarRequestParams = {
  value: MsgBarRequest,
};


export const registry = new Registry(msgTypes);

type Field = {
	name: string;
	type: unknown;
}
function getStructure(template) {
	const structure: {fields: Field[]} = { fields: [] }
	for (let [key, value] of Object.entries(template)) {
		let field = { name: key, type: typeof value }
		structure.fields.push(field)
	}
	return structure
}
const defaultFee = {
  amount: [],
  gas: "200000",
};

interface TxClientOptions {
  addr: string
	prefix: string
	signer?: OfflineSigner
}

export const txClient = ({ signer, prefix, addr }: TxClientOptions = { addr: "http://localhost:26657", prefix: "cosmos" }) => {

  return {
		
		async sendMsgMyMessageRequest({ value, fee, memo }: sendMsgMyMessageRequestParams): Promise<DeliverTxResponse> {
			if (!signer) {
					throw new Error('TxClient:sendMsgMyMessageRequest: Unable to sign Tx. Signer is not present.')
			}
			try {			
				const { address } = (await signer.getAccounts())[0]; 
				const signingClient = await SigningStargateClient.connectWithSigner(addr,signer,{registry});
				let msg = this.msgMyMessageRequest({ value: MsgMyMessageRequest.fromPartial(value) })
				return await signingClient.signAndBroadcast(address, [msg], fee ? fee : defaultFee, memo)
			} catch (e: any) {
				throw new Error('TxClient:sendMsgMyMessageRequest: Could not broadcast Tx: '+ e.message)
			}
		},
		
		async sendMsgBarRequest({ value, fee, memo }: sendMsgBarRequestParams): Promise<DeliverTxResponse> {
			if (!signer) {
					throw new Error('TxClient:sendMsgBarRequest: Unable to sign Tx. Signer is not present.')
			}
			try {			
				const { address } = (await signer.getAccounts())[0]; 
				const signingClient = await SigningStargateClient.connectWithSigner(addr,signer,{registry});
				let msg = this.msgBarRequest({ value: MsgBarRequest.fromPartial(value) })
				return await signingClient.signAndBroadcast(address, [msg], fee ? fee : defaultFee, memo)
			} catch (e: any) {
				throw new Error('TxClient:sendMsgBarRequest: Could not broadcast Tx: '+ e.message)
			}
		},
		
		
		msgMyMessageRequest({ value }: msgMyMessageRequestParams): EncodeObject {
			try {
				return { typeUrl: "/ignite.planet.mars.MsgMyMessageRequest", value: MsgMyMessageRequest.fromPartial( value ) }  
			} catch (e: any) {
				throw new Error('TxClient:MsgMyMessageRequest: Could not create message: ' + e.message)
			}
		},
		
		msgBarRequest({ value }: msgBarRequestParams): EncodeObject {
			try {
				return { typeUrl: "/ignite.planet.mars.MsgBarRequest", value: MsgBarRequest.fromPartial( value ) }  
			} catch (e: any) {
				throw new Error('TxClient:MsgBarRequest: Could not create message: ' + e.message)
			}
		},
		
	}
};

interface QueryClientOptions {
  addr: string
}

export const queryClient = ({ addr: addr }: QueryClientOptions = { addr: "http://localhost:1317" }) => {
  return new Api({ baseURL: addr });
};

class SDKModule {
	public query: ReturnType<typeof queryClient>;
	public tx: ReturnType<typeof txClient>;
	public structure: Record<string,unknown>;
	public registry: Array<[string, GeneratedType]> = [];

	constructor(client: IgniteClient) {		
	
		this.query = queryClient({ addr: client.env.apiURL });		
		this.updateTX(client);
		this.structure =  {
						AnotherType: getStructure(typeAnotherType.fromPartial({})),
						
		};
		client.on('signer-changed',(signer) => {			
		 this.updateTX(client);
		})
	}
	updateTX(client: IgniteClient) {
    const methods = txClient({
        signer: client.signer,
        addr: client.env.rpcURL,
        prefix: client.env.prefix ?? "cosmos",
    })
	
    this.tx = methods;
    for (let m in methods) {
        this.tx[m] = methods[m].bind(this.tx);
    }
	}
};

const IgntModule = (test: IgniteClient) => {
	return {
		module: {
			IgnitePlanetMars: new SDKModule(test)
		},
		registry: msgTypes
  }
}
export default IgntModule;