@page "/blockchains"
@page "/blockchains/{Smart}"
@using System.Text.RegularExpressions;
@using Console = HyperCube.Utils.AdvConsole;
@inject NavigationManager NavigationManager
@inject IJSRuntime JsRuntime
@using HyperCube.Models
@using Microsoft.AspNetCore.Identity;
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject UserManager<IdentityUser> UserManager

@attribute [Authorize]
<div class="tabs__content">
    <div class="tabs__controls">
        @if (account.Roles.Contains(Role.Admin) || account.Roles.Contains(Role.Initiator))
        {
            <a href="DocEdit" class="tabs__btn">Загрузка материалов</a>
        }
        @if (account.Roles.Contains(Role.Admin) || account.Roles.Contains(Role.Verifier))
        {
            <a href="Verifying" class="tabs__btn">Верификация</a>
        }
        <a class="tabs__btn">Библиотеки</a>
        @if (account.Roles.Contains(Role.Admin) || account.Roles.Contains(Role.Requester))
        {
            <a class="tabs__btn">Заказы</a>
        }
    </div>
</div>
<br>

@*<h1>Blazor is @Smart!</h1>*@
@code
{
    string hidecontr = "visible";
    string hidereceipt = "hidden";
    string result = "";
    string newcode = "";
    string newname = "";
    string balance = "";
    string sha3 = "";
    string function1 = "";
    string function_processed = "";
    string contractAddDisabled = "";
    string tokenContract = "0xe5D682717955d6C35d465A3485625C64655a04f4";

    string tokenName
    {
        get { return Blockchain.tokenName; }
        set { }
    }
    string tokenSymbol
    {
        get { return Blockchain.symbol; }
        set { }
    }
    string tokenDecimals
    {
        get { return Blockchain.decimals; }
        set { }
    }
    string tokenBalance
    {
        get { return Blockchain.tokenBalance; }
        set { }
    }
    string tokenAmount;
    string addressTo;

    SmartContract ctrSelected = new SmartContract();
    int ct;
    //ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff fff7
    string accountSelected;
    int contrtest
    {
        get
        {
            return ct;
        }
        set
        {
            ct = value;
            Console.WriteLine("ch contrtest val " + value);
            var ctr = GetContract(value);
            if (ctr != null)
            {
                Console.WriteLine("ctr found " + ctr.Name);
                ctrSelected = ctr;
            }
        }
    }
}

@if (Blockchain.blockChainsInitialized)
{
    <select @bind="AccountModel.GetCurrent().blockchain_selected" style="color:green">
        <option value=0>Ethereum Dev Network</option>
        <option value=1>Ethereum Test Network</option>
    </select>
    <p><b>@Blockchain.GetMain().url:@Blockchain.GetMain().port </b><br /> <b>Address:</b> @Blockchain.GetMain().address<br /> <b>Balance:</b> @Blockchain.GetMain().balance</p>

    @*@foreach(var bc in Blockchain.loaded.Values)
               {
            <p>
                <b>
                    @bc.url:@bc.port
                </b>, address: @bc.address
            </p>
        }*@

    @*<p>@AccountModel.GetCurrent().blockchain_selected</p>*@
    <br>

    <p></p>
    <p style="visibility:@hidecontr">
        Add smart contract:
    <p><input id="newname" @bind="newname" placeholder="Имя нового контракта" /></p>
    <p><input id="newcode" size="100" @bind="newcode" name="code" type="text" placeholder="Исходный код" /></p>
    <p><input id="bytecode" size="100" @bind="bytecode" name="bytecode" type="text" placeholder="Байткод" @bind:event="oninput" /></p>
    <p><input id="function1" size="100" @bind="function1" name="function1" type="text" placeholder="Функция №1 - Объявление" /></p>
    <p><input disabled id="function_processed" size="100" @bind="function_processed" name="function_processed" type="text" placeholder="Функция" /></p>
    <button @onclick="checkCode">checkCode</button>
    <div style="visibility: @contractAddDisabled">
        <button @onclick="AddContract">Add</button>
    </div>
    @*<div>
            <button @onclick="TestHTTP">TestHTTP</button>
        </div>*@

    <p><input id="getsha3" size="100" @bind="sha3" name="getsha3" type="text" placeholder="SHA3" @bind:event="oninput" /></p>
    @*<button @onclick="GetSHA3_2">GetSHA3</button>*@
    @*<p>
            0x60806040526000805534801561001457600080fd5b50610101806100246000396000f3006080604052600436106053576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680635b34b966146058578063a87d942c14606c578063f5c5ad83146094575b600080fd5b348015606357600080fd5b50606a60a8565b005b348015607757600080fd5b50607e60ba565b6040518082815260200191505060405180910390f35b348015609f57600080fd5b5060a660c3565b005b60016000808282540192505081905550565b60008054905090565b600160008082825403925050819055505600a165627a7a723058207815571f5c1d82bff3c0512a4cbc7a1f1c2063fa9a0de61913b76925f041e9ed0029
        </p>*@
    <br />
    </p>
    <div>
        <button @onclick="ImportERC20">ImportERC20</button>
        <p><input id="tc" size="100" @bind="tokenContract" name="code" type="text" placeholder="Адрес контракта токена" /></p>
        <p><input id="tn" size="100" @bind="tokenName" name="code" type="text" placeholder="" /></p>
        <p><input id="ts" size="100" @bind="tokenSymbol" name="code" type="text" placeholder="" /></p>
        <p><input id="td" size="100" @bind="tokenDecimals" name="code" type="text" placeholder="" /></p>
        <p><input id="tb" size="100" @bind="tokenBalance" name="code" type="text" placeholder="" /></p>
    </div>
    <div>
        <button @onclick="TransferToken">Transfer</button>
        <p><input id="tc" size="100" @bind="tokenAmount" name="code" type="text" placeholder="Количество" /></p>
        <p><input id="tn" size="100" @bind="addressTo" name="code" type="text" placeholder="Адрес получателя" /></p>

    </div>

    @*<p style="visibility:@hidereceipt">
            Get smart contract address:
            <button @onclick="GetReceipt">Check transaction receipt</button>
            <input id="bytecode" size="100" @bind="bytecode" name="bytecode" type="text" placeholder="Transaction address" @bind:event="oninput">
            <br />
        </p>*@
    <p>
        <select @bind="contrtest">
            <option value="0">[Select Contract]</option>
            @if (Blockchain.loaded.Count > 0)
            {
                result = Blockchain.loaded.Count.ToString();
                if (Blockchain.GetMain().contracts.Count > 0)
                {
                    @foreach (var c in Blockchain.GetMain().contracts.Values)
                    {
                        <option value="@c.ID">
                            [@c.ID] @c.Name [@c.Address]
                        </option>
                    }
                }
            }
        </select>
        <button @onclick="deleteContract">Удалить контракт</button>

    <p>
        @ctrSelected.Code
    </p>
    @ctrSelected.Name
    <br>
    @Blockchain.GetMain().id;
    <br />
    </p>

    <p>
        <select @bind="accountSelected">
            <option value="0">[Select Account]</option>
            @if (Blockchain.loaded.Count > 0)
            {
                @foreach (var acc in AccountModel.Loaded.Values)
                {
                    <option value="@acc.UUID">
                        [@acc.Email] @acc.Name
                    </option>
                }
            }
        </select>
        @*<button @onclick="CreateBlockchainAccount">CreateBlockchainAccount for @accountSelected</button>*@
        <button @onclick="GetBalance">GetBalance</button> Balance: @balance
        <button @onclick="Transfer50">Transfer 50</button>
        <button @onclick="Unlock">Unlock</button>
        <div>Wallet:@myWallet</div>
        <div>Token balance:@balanceHCB</div>
        @*<button @onclick="TransferContract">Transfer 10 by Contract</button>*@
        <button @onclick="EstimateGas">EstimateGas</button>
        @*<button onclick="window.location.href='@mypath'">Download 1</button>*@
        <button id="btn" @onclick="Dload">Dload</button>
    </p>

    <p>Result: @result, gas: @gas</p>
} 
@code
    {
    AccountModel account;
    private Random r = new Random();
    private string bcURL = Blockchain.URLdefault;
    private int bcport = Blockchain.defaultPort;
    private string bytecode = "";
    private string error = "";
    string lastTransAddr = "";
    string contractAddress = "";
    int focus = 0;
    string gas = "";


    async Task<string> Dload()
    {
        //string filepath = @"c:\Users\Администратор\AppData\Local\Ethereum\rinkeby\keystore\
        if (accountSelected != "" && accountSelected != null && accountSelected != "0")
        {
            var acc = AccountModel.Find(accountSelected);
            if (acc != null)
            {
                myWallet = await acc.GetOrCreateActualAddress(Blockchain.GetMain());
                string text = getFiles(myWallet);
                return await JsRuntime.InvokeAsync<string>("test", text);
            }
        }
        return "";
    }


    //Verify
    //function verify( address payable verifier, address payable initiator, uint8 article_value, uint8 verify_complexity)
    //0x608060405234801561001057600080fd5b50610190806100206000396000f3fe60806040526004361061001e5760003560e01c8063619837de14610023575b600080fd5b61009f6004803603608081101561003957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190803560ff1690602001909291905050506100a1565b005b600060058302820160ff1690508063ffffffff164710610153578473ffffffffffffffffffffffffffffffffffffffff166108fc8360ff169081150290604051600060405180830381858888f19350505050158015610104573d6000803e3d6000fd5b508373ffffffffffffffffffffffffffffffffffffffff166108fc6005850260ff169081150290604051600060405180830381858888f19350505050158015610151573d6000803e3d6000fd5b505b505050505056fea2646970667358221220847188fccb79ed4087ece85f7a8d9c3eaf187342166d7a66131b00a13bb0577b64736f6c63430007040033

    async Task<string> Unlock()
    {
        var bc = Blockchain.GetMain();
        var ret = await bc.RunFunction("personal_unlockAccount", $"\"{bc.address}\",\"test_Password_212\",0");
        //address, passphrase, duration
        //{ "method": "personal_unlockAccount", "params": [string, string, number]}
        return ret;
    }

    async Task ImportERC20()
    {
        await Blockchain.GetMain().ImportERC20(tokenContract);
        //await Blockchain.GetMain().ImportERC20("0x413D9500A675d9b645034aC5f4325BF12ddeb7c1");
    }

    async Task TransferToken()
    {
        await Blockchain.GetMain().TransferToken(Blockchain.GetMain().address, tokenContract, addressTo, tokenAmount);
    }

    async Task EstimateGas()
    {
        gas = await Blockchain.GetMain().GetEstimatedGasContractAdd(ctrSelected.ByteCode);
    }

    async Task deleteContract()
    {
        var main = Blockchain.GetMain();
        if (main != null)
        {
            main.contracts.Remove(ctrSelected.ID);
            main.contractNames.Remove(ctrSelected.Name);
            MySQLConnector.Instance().SQLInsert($"delete from smart_contracts where id ={ctrSelected.ID}");
            MySQLConnector.Instance().SQLInsert($"delete from functions where contract_id ={ctrSelected.ID}");
            ctrSelected = null;
        }
    }

    async Task checkCode()
    {
        ////string pattern = @"function\s+(\S+)\s*\((.*)\)\s*{.*}";
        //string pattern = @"function\s+(\S+)\s*\((.*)\).*";
        //string replacement_name = "$1";
        //string replacement_params = "$2";
        //string input = function1;
        //string resultname = Regex.Replace(input, pattern, replacement_name).Trim();
        //string param_pattern = @"(uint8|address)";
        //var final = resultname + "(";
        //if (input != resultname)
        //{
        //    //function_processed += "name " + resultname + " ";
        //    string resultparams = Regex.Replace(input, pattern, replacement_params).Trim();
        //    if (input != resultparams)
        //    {
        //        //function_processed += "params " + resultparams+" matches: ";
        //        int i = 0;
        //        foreach (Match match in Regex.Matches(resultparams, param_pattern))
        //        {
        //            if (i > 0)
        //                final += "," + match.Value;
        //            else
        //                final += match.Value;
        //            i++;
        //        }
        //    }
        //}
        //function_processed = final + ")";
        //sha3 = await GetSHA3(function_processed);
        //getFiles();
        function_processed = await Blockchain.GetMain().compileFunction(function1, false);

        if (function1 != "()" && function1 != "")
            contractAddDisabled = "";
        else
            contractAddDisabled = "visible";
    }

    async Task<string> GetSHA3(string code)
    {
        var res = await Blockchain.GetMain().GetSHA3(code);
        Console.WriteLine($"GetSHA3 {code} {res}");
        var ret = res.Substring(2, 8);
        return ret;
    }

    async Task<string> GetSHA3_2()
    {
        var res = await Blockchain.GetMain().GetSHA3(sha3);
        Console.WriteLine($"GetSHA3 {res}");
        var ret = res.Substring(2, 8);
        return ret;
    }

    //protected async Task TransferContract()
    //{
    //    var ttt = "123";
    //    Console.WriteLine($"len  {ttt.Length}");
    //    try
    //    {
    //        var myacc = AccountModel.Current;
    //        Console.WriteLine($"TransferContract run");
    //        Console.WriteLine($"TransferContract {myacc.Name}");

    //        var recipient = AccountModel.Find(accountSelected);
    //        if (recipient != null)
    //        {
    //            var bc = Blockchain.GetMain();
    //            //var b2h = Blockchain.bin2hex("getCount()");
    //            //Console.WriteLine("bin2hex " + b2h);
    //            var part1 = await Blockchain.GetSHA3("myTransfer(address)");
    //            //var part2 = await Blockchain.GetSHA3(recipient.eth_address);
    //            var zerofill = Blockchain.zerofill(part1.Substring(0, 10), 32, true);
    //            //var zerofill2 = Blockchain.zerofill(part2, 32, true);
    //            var radr = await recipient.GetOrCreateActualAddress(bc);
    //            var paramstring = "0x" + zerofill + radr.Remove(0, 2);
    //            Console.WriteLine($"paramstring {paramstring}");

    //            //todo pack myTransfer(address)
    //            //todo pack contr.Address

    //            if (bc.contractNames.ContainsKey("Transfer"))
    //            {
    //                var contr = bc.contractNames["Transfer"];
    //                var res = await bc.RunContractWrite(contr.Address, $"{paramstring}");
    //                Console.WriteLine("TransferContract result " + res);

    //                var receipt = await bc.GetReceipt(res);
    //                Console.WriteLine("TransferContract receipt " + receipt);
    //            }
    //        }
    //        //TODO run smart contract with verifier wallet
    //    }
    //    catch (Exception e)
    //    {
    //        Console.WriteLine(e.Message);
    //    }
    //}

    private async Task Transfer50()
    {
        var acc = AccountModel.Find(accountSelected);
        var bc = Blockchain.GetMain();
        var addr = await acc.GetOrCreateActualAddress(bc);
        var res = await bc.SendTransaction(Blockchain.GetMain().address, addr, 50);
    }

    private async Task GetBalance()
    {
        Console.WriteLine("accountSelected " + accountSelected);
        if (accountSelected != "" && accountSelected != null && accountSelected != "0")
        {
            var acc = AccountModel.Find(accountSelected);
            if (acc != null)
            {
                myWallet = await acc.GetOrCreateActualAddress(Blockchain.GetMain());
                balance = await acc.GetBalance();
            }
        }
        else
        {
            balance = await Blockchain.GetMain().GetBalance();
        }

    }

    //private async Task CreateBlockchainAccount(Blockchain bc, string pass)
    //{
    //    AccountModel account = AccountModel.Find(accountSelected);
    //    if (account != null)
    //    {
    //        var res = await bc.CreateBlockchainAccount(account, pass);
    //    }
    //}


    private async Task ChangeContract()
    {
        Console.WriteLine("ChangeContract " + contrtest);
        //TODO result as transaction addr
        //result = await Blockchain.loaded[0].GetReceipt(result);
    }


    private async Task RunContract()
    {
        //TODO result as transaction addr
    }

    private async Task AddContract()
    {
        if (Blockchain.loaded.Count > 0)
        {
            var taddr = await Blockchain.GetMain().AddContract(newname, newcode, bytecode);
            if (taddr.Length > 0 && taddr[0] != "")
            {
                result = taddr[0].ToString();
                //hidereceipt = "visible";
                var caddr = await Blockchain.GetMain().GetReceipt(result, true);
                if (caddr != "")
                {
                    result = "contractAddress: " + caddr;
                    contractAddress = caddr;

                    //var id = (int) taddr[1];
                    var smc = taddr[1] as SmartContract;//Blockchain.GetMain().contracts[id];
                    smc.Address = contractAddress;
                    MySQLConnector.Instance().SQLInsert($"update smart_contracts set address='{contractAddress}' where id= {smc.ID}");
                    //var run = await Blockchain.GetMain().RunContractWrite(contractAddress, "0x11111111");
                    //result = "run: " + run;

                    smc.AddFunction(function_processed, sha3);
                }
            }
        }
        //private Post post = new Post();
    }

    SmartContract GetContract(int id)
    {
        if (Blockchain.GetMain().contracts.ContainsKey(id))
            return Blockchain.GetMain().contracts[id];
        else
            return null;
    }

    protected override async Task OnInitializedAsync()
    {
        //Console.WriteLine($"Blazor is {Smart}");

        account = AccountModel.Current;
        Console.WriteLine($"Blockchains OnInitializedAsync");
        await GetBalance();
    }

    //private async Task GetBlockChain()
    //{
    //    //if (Blockchain.loaded.Count == 0)
    //    //{
    //    Blockchain bc = new HyperCube.Models.Blockchain(bcURL, bcport);
    //    result = await bc.Initialize();
    //    if (result != "")
    //        hidecontr = "visible";
    //    //bcURL = bc.GetAddress();
    //    //bc.ExecuteContract();
    //    //bcURL = bc.address;
    //    //hidecontr = "hidden";
    //    //}

    //    //private Post post = new Post();
    //}
}
