class ContractRawParser(BaseParser):
    colIndex = [
        ColumnIndex(name="trans_id", fromAppend=True),
        ColumnIndex(name="ret", fromAppend=True),
        ColumnIndex(
            name="bytes_hex",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
    ]

    def __init__(self, table):
        self.table = table

    def Parse(self, writer, data, appendData):
        if len(self.colIndex) == 0 or self.table is None:
            logging.error("请勿直接调用抽象类方法,请实例化类并未对象变量赋值")
            # raise
            return False

        vals = []
        for col in self.colIndex:
            if col.FromAppend:
                vals.append(appendData[col.name])
        vals.append(bytes2HexStr(data))  # TODO:how to decode
        self.Write(writer, vals)
        return True
class ContractBaseParser(BaseParser):
    colIndex = [
        ColumnIndex(name="trans_id", fromAppend=True),
        ColumnIndex(name="ret", fromAppend=True),
        ColumnIndex(
            name="provider",
            oc=OriginColumn(name="provider",
                            colType="bytes",
                            castFunc=autoDecode),
        ),
        ColumnIndex(
            name="name",
            oc=OriginColumn(name="ContractName",
                            colType="bytes",
                            castFunc=autoDecode),
        ),  # TODO: not b2hs?
        ColumnIndex(name="permission_id",
                    oc=OriginColumn(name="permission_id", colType="int32")),
    ]

    def Parse(self, writer, data, appendData):
        # if self.table == "account_create_contract":
        #     print("account_create_contract: ", data)
        #     print("account_create_contract append data: ", appendData)
        self.contract.ParseFromString(data)
        return super().Parse(writer, self.contract, appendData)
class freeze_balance_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="frozen_balance",
            oc=OriginColumn(name="frozen_balance", colType="int64"),
        ),
        ColumnIndex(
            name="frozen_duration",
            oc=OriginColumn(name="frozen_duration", colType="int64"),
        ),
        ColumnIndex(
            name="resource",
            oc=OriginColumn(name="resource", colType="int"),
        ),
        ColumnIndex(
            name="receiver_address",
            oc=OriginColumn(name="receiver_address",
                            castFunc=addressFromBytes),
        ),
    ]
    table = "freeze_balance_contract"
class exchange_create_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="first_token_id",
            oc=OriginColumn(name="first_token_id",
                            castFunc=autoDecode),  # TODO:type
        ),
        ColumnIndex(
            name="first_token_balance",
            oc=OriginColumn(name="first_token_balance", colType="int64"),
        ),
        ColumnIndex(
            name="second_token_id",
            oc=OriginColumn(name="second_token_id",
                            castFunc=autoDecode),  # TODO:type
        ),
        ColumnIndex(
            name="second_token_balance",
            oc=OriginColumn(name="second_token_balance", colType="int64"),
        ),
    ]
    table = "exchange_create_contract"
class market_sell_asset_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="sell_token_id",
            oc=OriginColumn(name="sell_token_id",
                            castFunc=autoDecode),  # TODO:type
        ),
        ColumnIndex(
            name="sell_token_quantity",
            oc=OriginColumn(name="sell_token_quantity", colType="int64"),
        ),
        ColumnIndex(
            name="buy_token_id",
            oc=OriginColumn(name="buy_token_id",
                            castFunc=autoDecode),  # TODO:type
        ),
        ColumnIndex(
            name="buy_token_quantity",
            oc=OriginColumn(name="buy_token_quantity", colType="int64"),
        ),
    ]
    table = "market_sell_asset_contract"
class account_update_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="account_name",
            oc=OriginColumn(name="account_name", castFunc=autoDecode),
        ),
    ]
    table = "account_update_contract"
class set_account_id_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="account_id",
            oc=OriginColumn(name="account_address"),
        ),
    ]
    table = "set_account_id_contract"
class proposal_delete_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="proposal_id",
            oc=OriginColumn(name="account_address", colType="int64"),
        ),
    ]
    table = "proposal_delete_contract"
class WitnessCreateContractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="url",
            oc=OriginColumn(name="url", castFunc=autoDecode),
        ),
    ]
    table = "witness_create_contract"
class market_cancel_order_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="order_id",
            oc=OriginColumn(name="order_id", castFunc=autoDecode),  # TODO:type
        ),
    ]
    table = "market_cancel_order_contract"
class update_brokerage_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="brokerage",
            oc=OriginColumn(name="brokerage", colType="int32"),
        ),
    ]
    table = "update_brokerage_contract"
class clear_abi_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="contract_address",
            oc=OriginColumn(name="contract_address",
                            castFunc=addressFromBytes),
        ),
    ]
    table = "clear_abi_contract"
class TransferContractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="to_address",
            oc=OriginColumn(name="to_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="amount",
            oc=OriginColumn(name="amount", colType="int64"),
        ),
    ]
    table = "transfer_contract"
class update_energy_limit_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="contract_address",
            oc=OriginColumn(name="contract_address",
                            castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="origin_energy_limit",
            oc=OriginColumn(name="origin_energy_limit", colType="int64"),
        ),
    ]
    table = "update_energy_limit_contract"
class unfreeze_asset_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
    ]
    table = "unfreeze_asset_contract"
class withdraw_balance_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
    ]
    table = "withdraw_balance_contract"
class update_setting_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="contract_address",
            oc=OriginColumn(name="contract_address",
                            castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="consume_user_resource_percent",
            oc=OriginColumn(name="consume_user_resource_percent",
                            colType="int64"),
        ),
    ]
    table = "update_setting_contract"
class FrozenSupplyParser(ContractBaseParser):
    def __init__(self):
        self.contract = asset_issue_contract_pb2.AssetIssueContract()

    table = "asset_issue_contract_frozen_supply"
    colIndex = [
        ColumnIndex(
            name="trans_id",
            fromAppend=True,
        ),
        ColumnIndex(
            name="frozen_amount",
            oc=OriginColumn(name="frozen_amount", colType="int64"),
        ),
        ColumnIndex(
            name="frozen_days",
            oc=OriginColumn(name="frozen_days", colType="int64"),
        ),
    ]
class exchange_withdraw_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="exchange_id",
            oc=OriginColumn(name="exchange_id", colType="int64"),
        ),
        ColumnIndex(
            name="token_id",
            oc=OriginColumn(name="token_id", castFunc=autoDecode),  # TODO:type
        ),
        ColumnIndex(
            name="quant",
            oc=OriginColumn(name="quant", colType="int64"),
        ),
    ]
    table = "exchange_withdraw_contract"
class participate_asset_issue_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="to_address",
            oc=OriginColumn(name="to_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="asset_name",
            oc=OriginColumn(name="asset_name", castFunc=autoDecode),
        ),
        ColumnIndex(
            name="amount",
            oc=OriginColumn(name="amount", colType="int64"),
        ),
    ]
    table = "participate_asset_issue_contract"
class trigger_smart_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="contract_address",
            oc=OriginColumn(name="account_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="call_value",
            oc=OriginColumn(name="call_value", colType="int64"),
        ),
        ColumnIndex(
            name="data",
            oc=OriginColumn(name="data", colType="bytes"),
        ),
        ColumnIndex(
            name="call_token_value",
            oc=OriginColumn(name="call_token_value", colType="int64"),
        ),
        ColumnIndex(
            name="token_id",
            oc=OriginColumn(name="token_id", colType="int64"),
        ),
    ]
    table = "trigger_smart_contract"
class AccountCreateContractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        # owner_address: "Justin_Sun"
        # account_address: "AFv\330\036\026`K\330\341\334\252\330T\204&\231\365\272\002~"
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=ownerAddressDecode),
        ),
        ColumnIndex(
            name="account_address",
            oc=OriginColumn(name="account_address", castFunc=addressFromBytes),
        ),
        # TO REVIEW:
        # >>> c.account_type
        # Traceback (most recent call last):
        # File "<stdin>", line 1, in <module>
        # AttributeError: account_type
        # >>> c.account_type
        ColumnIndex(
            name="account_type",
            oc=OriginColumn(name="account_type", colType="int"),
        ),
    ]
    table = "account_create_contract"
class update_asset_contractParser(ContractBaseParser):
    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="description",
            oc=OriginColumn(name="description", castFunc=autoDecode),
        ),
        ColumnIndex(
            name="url",
            oc=OriginColumn(name="url", castFunc=autoDecode),
        ),
        ColumnIndex(
            name="new_limit",
            oc=OriginColumn(name="new_limit", colType="int64"),
        ),
        ColumnIndex(
            name="new_public_limit",
            oc=OriginColumn(name="new_public_limit", colType="int64"),
        ),
    ]
    table = "update_asset_contract"
class AssetIssueContractParser(ContractBaseParser):
    def __init__(self):
        self.frozenSupplyParser = FrozenSupplyParser()

    colIndex = ContractBaseParser.colIndex + [
        ColumnIndex(
            name="id",
            oc=OriginColumn(name="id", colType="string"),
        ),
        ColumnIndex(
            name="owner_address",
            oc=OriginColumn(name="owner_address", castFunc=addressFromBytes),
        ),
        ColumnIndex(
            name="name_",
            oc=OriginColumn(name="name", castFunc=autoDecode),
        ),
        ColumnIndex(
            name="abbr",
            oc=OriginColumn(name="abbr", castFunc=autoDecode),
        ),
        ColumnIndex(
            name="total_supply",
            oc=OriginColumn(name="total_supply", colType="int64"),
        ),
        ColumnIndex(
            name="trx_num",
            oc=OriginColumn(name="trx_num", colType="int32"),
        ),
        ColumnIndex(
            name="precision",
            oc=OriginColumn(name="precision", colType="int32"),
        ),
        ColumnIndex(
            name="num",
            oc=OriginColumn(name="num", colType="int32"),
        ),
        ColumnIndex(
            name="start_time",
            oc=OriginColumn(name="start_time", colType="int64"),
        ),
        ColumnIndex(
            name="end_time",
            oc=OriginColumn(name="end_time", colType="int64"),
        ),
        ColumnIndex(
            name="order_",
            oc=OriginColumn(name="order", colType="int64"),
        ),
        ColumnIndex(
            name="vote_score",
            oc=OriginColumn(name="account_address", colType="int32"),
        ),
        ColumnIndex(
            name="description",
            oc=OriginColumn(name="description", castFunc=autoDecode),
        ),
        ColumnIndex(
            name="url",
            oc=OriginColumn(name="url", castFunc=autoDecode),
        ),
        ColumnIndex(
            name="free_asset_net_limit",
            oc=OriginColumn(name="free_asset_net_limit", colType="int64"),
        ),
        ColumnIndex(
            name="public_free_asset_net_limit",
            oc=OriginColumn(name="public_free_asset_net_limit",
                            colType="int64"),
        ),
        ColumnIndex(
            name="public_free_asset_net_usage",
            oc=OriginColumn(name="public_free_asset_net_usage",
                            colType="int64"),
        ),
        ColumnIndex(
            name="public_latest_free_net_time",
            oc=OriginColumn(name="public_latest_free_net_time",
                            colType="int64"),
        ),
    ]
    table = "asset_issue_contract"

    def Parse(self, writer, data, appendData):
        ret = super().Parse(writer, data, appendData)
        if not ret:
            return False
        frozenAppend = {"trans_id": appendData["trans_id"]}
        for f in self.contract.frozen_supply:
            ret = self.frozenSupplyParser.Parse(writer, data, frozenAppend)
            if not ret:
                return False
        return True