/*
 * Copyright (C) 2021 Zilliqa
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package mpt

import (
	"github.com/Zilliqa/gozilliqa-sdk/v3/core"
	"github.com/Zilliqa/gozilliqa-sdk/v3/util"
	"strings"
	"testing"
)

func TestVerify(t *testing.T) {
	// key is contract address
	contractAddress := "6d84363526a2d764835f8cf52dfeefe80a360fac"
	key := []byte(contractAddress)

	// account proof
	proofString := []string{
		"F851808080A033B8F541699405A9EC761FEFDE1678FCC5D6C1443FC45EA6202CFFE17613BACF8080A00ABACD35E0C4C5D0230FDF384301988E7CEF4363905A044ED9C4D4352377194780808080808080808080",
		"F851808080A0C2F33F0FC3E2B3F5B16F3781C8BA48039AD5F930F8112141D8D81F4DFF291AC28080A08FD08A14F20DE80B55152B68F28D82744ADC22F0B06C2D52313751265004B24580808080808080808080",
		"F871808080A0636EEDCCD9E2391FB28A4E03D890D7B669F004218408480F223014617A80D2CEA04F172A394426A7AAC493F5D1AC25EFBDE106A541125ECB542EB9C5D2386552BCA07C71C74861FA4B6C07E4FC104C6C94B0E8FF84863D7F1EF133FBB1209CFDE7DB8080808080808080808080",
		"F886A7203834333633353236613264373634383335663863663532646665656665383061333630666163B85C080112120A10000000000000000000000000000000001800222067636FDAEA4993850EE2A95078D184ED666472AA1A08B9353D9D3C4E8C9186B32A20818808E9735CF5F74C381CFDA911C5E94A9F115B235D0A79ECF1D27961A9E0A4",
		"F90111A01DAD0528BD2BAE99521C5051F7D39CEEE6928A3C2304D3A71DC235B0D048824BA06BC2BD3B0776EC49538E0A398CCA1E55895D5726F6F95D2BECEE775F40EE8214A0D44FBB22463EFE2B0358EBC0A9514A529F2E5F5558AD51843DE43F598BE9057BA06677B6E530D944DDDCE748EE2A696CF9B3EAE4587DC2B765958F3A3FBDADF963A02EDBC33F947AA821D5A25F8302E7939497BBB997344D4F6C59E0C6DF210CDF4380A02AD9513C693E32A736A50C6741E3F7B1C1E46AC714129D6B09270CD9D032E93FA004DC9C2A21CE245AAC087F487E45C6078847A53AF149FC487DCB62D97D4D4C4380A0C9F02AF007B55C410D53FD56ABE35FDA3799D6F66C7BBF67EEC76F8C422D703380808080808080",
	}
	var proof [][]byte

	for _, p := range proofString {
		bytes := util.DecodeHex(p)
		proof = append(proof, bytes)
	}

	db := NewFromProof(proof)

	// StateRootHash from tx block
	root := util.DecodeHex("6142ce35237ba92eb734a5442f4d22dbc4f00c7acf88d0ab07333b60e83dd93e")
	value, err1 := Verify(key, db, root)
	if err1 != nil {
		t.Fatal(err1.Error())
	}
	t.Log(util.EncodeHex(value))

	storageKey := core.GenerateStorageKey(contractAddress, "zilToPolyTxHashMap", []string{"0"})
	hashedStorageKey := util.Sha256(storageKey)
	t.Log("hashed storage key is: " + util.EncodeHex(hashedStorageKey))

	key3 := []byte((util.EncodeHex(hashedStorageKey)))

	// state proof
	proofString3 := []string{
		"E213A0AA4095FF127577FEBF2885E4EF1D8E38923E8FFB15E27A389DC74C8A0C807997",
		"F851808080A018FFAF440F24DCC20A482934470607977A6D8E84952240A158053B338B3B89C08080A03DF26B59D214F7F917BF331187A4147B68163B6BB628845593DD9FA649DCC24A80808080808080808080",
		"F851A041F80919CC6E7ACF60A0B2A7F6BCAD5A88DF48879BCB642A43DFC8C15B84B6958080808080808080A002A0CB937E38D331EC347FF1993DE57517B2951480EA9CF637659EAADAA4D9C480808080808080",
		"F887B83F206264393164653636643937653639333031313831373962613466313833366333363663346362333330396136623335346432366635326162623261616336B8442230783730326662333264633035363061356264653139353132633835656631373562663734333735386564383763396630353034303234323534636466306630376422",
		"F8B180A0AD3215C996AB8F8CB96D38F2CB801A799A04660CB850833607E0999DFA3F321EA0A2874883F1D6028DD9E3807EABB30A997D9539257AD2C24724FEFF189BC5B13FA07E1BFFC5C44C92C9C65C3B8827543FF18F3F261550A8D4DCFAF784771C0F545DA039EA5792159BABAD0431C7FD9D9329AD1BDEE6DDC39DA3A0D60AB0FA573EE045A03031D0495A4921B9E6794C5F811AC35798137861591489F92208E465EA75DB3F8080808080808080808080",
	}
	var proof3 [][]byte

	for _, p := range proofString3 {
		bytes := util.DecodeHex(p)
		proof3 = append(proof3, bytes)
	}

	db3 := NewFromProof(proof3)

	accountBase, _ := core.AccountBaseFromBytes(util.DecodeHex("080112120a10000000000000000000000000000000001800222067636fdaea4993850ee2a95078d184ed666472aa1a08b9353d9d3c4e8c9186b32a20818808e9735cf5f74c381cfda911c5e94a9f115b235d0a79ecf1d27961a9e0a4"))
	root3 := accountBase.StorageRoot
	value3, err2 := Verify(key3, db3, root3)

	if err2 != nil {
		t.Fatal(err2.Error())
	}

	t.Log(string(value3))
}

func TestGenerateHashedStorageKey(t *testing.T) {
	contractAddress := "6d84363526a2d764835f8cf52dfeefe80a360fac"
	storageKey := core.GenerateStorageKey(contractAddress, "zilToPolyTxHashMap", []string{"0"})
	hashedStorageKey := util.Sha256(storageKey)
	t.Log("hashed storage key is: " + strings.ToUpper(util.EncodeHex(hashedStorageKey)))
}
