
import {system,world, ItemStack} from "@minecraft/server"
import {ModalFormData,ActionFormData} from "@minecraft/server-ui"



/*
    I know how this code works
    I don't know how i made this shit in less than one week tho
*/

const coinList = ["Copper coin(s)","Tin coin(s)","Iron coin(s)","Platinum coin(s)","Nickel coin(s)","Netherite coin(s)","Void coin(s)"]
const coinIdList =["edx:copper_coin","edx:tin_coin","edx:iron_coin","edx:platinium_coin","edx:nickel_coin","edx:netherite_coin","edx:void_coin"]
const itemTypeList =["Normal Item","Block","Held item"]
//owner
export function VenderOwnerOpen(player,vender,item)
{
    var form = new ActionFormData()
    form.title("Personal Vender")
    form.body(GenerateVenderStats(vender))
    form.button(item!=undefined?"Change the selling item":"Withdraw selling items")
    form.button("Withdraw coins")
    form.button("Settings")
    form.button("Remove the vender")
    form.show(player).then(result => {
    if (result.selection === 0) {
        if(item!=undefined)
        {
            if(GetVenderItem(vender) == undefined || !ItemSame(GetVenderItem(vender),item))
                VenderSellingSettingDifferent(player,vender,item)
            else
                VenderSellingSettingSame(player,vender,item)
        }
        else
        {
            VenderSellingSettingWithdraw(player,vender,item)
        }
        
    }
    else if (result.selection === 1) {
        WithdrawCoins(player,vender)
    }
    else if (result.selection === 2) {
        VenderEditor(player,vender,item)
    }
    else if (result.selection === 3) {
        VenderRemoveConfirm(player,vender,item)
    }
    })
}

function VenderEditor(player,vender)
{
    const [venderPrice,venderCoinType] = PriceCalculator(vender.getDynamicProperty("price"))
    const venderWelcomeText = vender.getDynamicProperty("welcome_text")
    const venderOpen = vender.getProperty("edx:open")
    const venderItemType = vender.getProperty("edx:item_type")
    let form = new ModalFormData()
    form.title("Personal Vender");
    form.textField("Welcome Text", venderWelcomeText)
    form.dropdown("Coin Type", coinList, {defaultValueIndex:venderCoinType})
    form.slider("Price (in 'coin type')", 0, 9, {valueStep:1, defaultValue:venderPrice})
    form.dropdown("Type of the item you're selling", itemTypeList, {defaultValueIndex:venderItemType})
    form.toggle("Is Open", {defaultValue:venderOpen})
    form.show(player).then(r => {
        // This will stop the code when the player closes the form
        if (r.canceled) return;
    
        // This will assign every input their own variable
        let [ welcomeText, coinType, price,itemType, isOpen ] = r.formValues;
        if(welcomeText=="")welcomeText=venderWelcomeText;
        vender.setDynamicProperty("welcome_text", welcomeText);
        if(isOpen=="") isOpen = venderOpen
        vender.setProperty("edx:open",isOpen);
        if(coinType>10) coinType=venderCoinType //to patch a bug
        vender.setDynamicProperty("price", price*10**coinType);
        if(itemType=="") itemType=venderItemType;
        vender.setProperty("edx:item_type", itemType);
        TestClose(vender,player)
        player.playSound('lodestone_compass.link_compass_to_lodestone');
    })
}

function VenderSellingSettingDifferent(player,vender,item){
    
    var form = new ActionFormData()
    form.title("Personal Vender")
    form.body(GenerateVenderSellingSettingDifferent(vender,item))
    form.button("Yes")
    form.button("No, Withdraw selling items")
    form.button("Back")
    form.show(player).then(result => {
    if (result.selection === 0) {
        item = player.getComponent('equippable').getEquipment('Mainhand')
        ReplaceVenderItem(vender,item,player)
    }
    else if (result.selection === 1) {
        WithdrawVenderItem(player,vender)
    }
    else if (result.selection === 2) {
        VenderOwnerOpen(player,vender,item)
    }
    })
}
function VenderSellingSettingSame(player,vender,item){
    var form = new ActionFormData()
    form.title("Personal Vender")
    form.body(GenerateVenderSellingSettingSame(vender,item))
    form.button("Yes")
    form.button("No, Withdraw selling items")
    form.button("Back")
    form.show(player).then(result => {
    if (result.selection === 0) {
        item = player.getComponent('equippable').getEquipment('Mainhand')
        AddVenderItem(player,vender,item)
    }
    else if (result.selection === 1) {
        WithdrawVenderItem(player,vender)
    }
    else if (result.selection === 2) {
        VenderOwnerOpen(player,vender,item)
    }
    })
}

function VenderSellingSettingWithdraw(player,vender,item){
    var form = new ActionFormData()
    form.title("Personal Vender")
    form.body(GenerateVenderSellingSettingWithdraw(vender))
    form.button("Withdraw selling items")
    form.button("Back")
    form.show(player).then(result => {
    if (result.selection === 0) {
        WithdrawVenderItem(player,vender)
    }
    else if (result.selection === 1) {
        VenderOwnerOpen(player,vender,item)
    }
    })
}

function GenerateVenderStats(vender)
{
    const open =vender.getProperty("edx:open")
    const [venderPrice,venderCoinType] = PriceCalculator(vender.getDynamicProperty("price"))
    return {rawtext: [{text: open?"§aThis vender is Open":"§cThis vender is Closed"},{text: "\n§eCurrently selling:§r "} , {text: vender.getDynamicProperty("item_name")} , {text:" ("} , {text:vender.getDynamicProperty("item_id")} , {text:")\n"},
            {text: "§eLeft amount:§r "} , {text: vender.getDynamicProperty("item_amount").toString()} , {text:"\n"},
            {text: "§ePrice:§r "} , {text: venderPrice.toString()} , {text:" "} , {text: coinList[venderCoinType].toString()} , {text:"\n"},
            {text: "§eCoins stored:§r "} , {text: CoinNumberToString(vender.getDynamicProperty("coin_amount"))} , {text:"\n"},
            {text:"To add an item in the vender, sneak+interact with it with the item in your hand "}]}

}
function GenerateVenderSellingSettingDifferent(vender,item)
{
    return {rawtext:[{text: "§eCurrently selling:§r "} , {text: vender.getDynamicProperty("item_name")} , {text:" ("} , {text:vender.getDynamicProperty("item_id")} , {text:")\n"},
            {text: "§eLeft amount:§r "} , {text: vender.getDynamicProperty("item_amount").toString()} , {text:"\n"},
            {text:"Do you want to replace §a"} , {text: vender.getDynamicProperty("item_name").toString()} , {text:" §rwith §a"} , {text: GetItemName(item)}, {text: "§r?\n"}]}

}
function GenerateVenderSellingSettingSame(vender,item)
{
    return {rawtext:[{text: "§eCurrently selling:§r "} , {text: vender.getDynamicProperty("item_name")} , {text:" ("} , {text:vender.getDynamicProperty("item_id")} , {text:")\n"},
            {text: "§eLeft amount:§r "} , {text: vender.getDynamicProperty("item_amount").toString()} , {text:"\n"},
            {text:"Do you want to add "} , {text: item.amount.toString()} , {text:" "} , {text: GetItemName(item)}, {text: "§r?\n"}]}

}
function GenerateVenderSellingSettingWithdraw(vender)
{
    return {rawtext:[{text: "§eCurrently selling:§r "} , {text: vender.getDynamicProperty("item_name")} , {text:" ("} , {text:vender.getDynamicProperty("item_id")} , {text:")\n"},
            {text: "§eLeft amount:§r "} , {text: vender.getDynamicProperty("item_amount").toString()} , {text:"\n"},
            {text:"To add an item in the vender, sneak+interact with it with the item in your hand "}]}

}

function GetVenderItem(vender)
{
    return vender.getComponent("minecraft:inventory").container.getItem(0)

}
function SetVenderItem(player,vender,item)
{
    if(item.getTags()?.includes("coin"))
    {
        player.sendMessage("§cBlimey! No dupplicatin' o' doubloons while I'm standin' watch!");
        return
    }
    VenderAddEasterEgg(item,player)
    const newitem = item.clone()
    vender.setDynamicProperty("item_amount",newitem.amount)
    newitem.amount = 1
    vender.setDynamicProperty("item_name",GetItemName(newitem))
    vender.setDynamicProperty("item_id",newitem.typeId)
    vender.runCommand(`replaceitem entity @s slot.weapon.mainhand 0 ${newitem.typeId}`)
    player.getComponent('equippable').setEquipment('Mainhand', undefined);  
    vender?.getComponent("minecraft:inventory")?.container?.setItem(0, newitem)
}
function RemoveVenderItem(vender)
{
    vender.setDynamicProperty("item_amount",0)
    vender.setDynamicProperty("item_name","Boredom")
    vender.setDynamicProperty("item_id","edx:boredom")
    vender.runCommand(`replaceitem entity @s slot.weapon.mainhand 0 minecraft:air`)
    vender?.getComponent("minecraft:inventory")?.container?.setItem(0,undefined)
    vender.setProperty("edx:open",false)
}

function ReplaceVenderItem(vender,item,player)
{
    if(item.getTags()?.includes("coin"))
    {
        player.sendMessage("§cBlimey! No dupplicatin' o' doubloons while I'm standin' watch!");
        return
    }
    if(GetVenderItem(vender)!=undefined)
    {
        
        const venderItem = GetVenderItem(vender).clone()
        for (let i = 1; i <= vender.getDynamicProperty("item_amount") ; i++) {
                        system.runTimeout(() => {
           player.dimension.spawnItem(venderItem, player.location);
                            },3)   
            
        }
    }
    SetVenderItem(player,vender,item) 
    
    
}
function WithdrawVenderItem(player,vender)
{
    if(GetVenderItem(vender)!=undefined)
    {
        const venderItem = GetVenderItem(vender).clone()
        for (let i = 1; i <= vender.getDynamicProperty("item_amount") ; i++) {
                                    system.runTimeout(() => {
           player.dimension.spawnItem(venderItem, player.location);
                            },3)   
            
        }
    }
    RemoveVenderItem(vender) 
    
}
function AddVenderItem(player,vender,item)
{
    vender.setDynamicProperty("item_amount",vender.getDynamicProperty("item_amount") + item.amount)
    player.getComponent('equippable').setEquipment('Mainhand', undefined);  
}

function GetItemName(item)
{
    var start=false
    var name=''
    for(let i = 0; i < item.typeId.length ; i++) {
        if(start==true)
        {
            if(item.typeId[i]!='_')
                if(item.typeId[i-1]=='_' || item.typeId[i-1]==':')
                    name+=item.typeId[i].toUpperCase()
                else
                    name+=item.typeId[i]
            else
                name+=' '
        }

        if(item.typeId[i]==':') start=true;

    }
    return name
}

function ItemSame(venderItem,playerItem)
{
    const enchant = venderItem.getComponent('enchantable')?.getEnchantments() == playerItem.getComponent('enchantable')?.getEnchantments()
    const dura = venderItem.getComponent('durability')?.damage == playerItem.getComponent('durability')?.damage
    const type = venderItem.typeId == playerItem.typeId
    const name = venderItem.nameTag == playerItem.nameTag
    return type && enchant && dura && name

}

function WithdrawCoins(player,vender)
{
    let inv = player.getComponent("inventory").container
    const coinsList = CoinNumberToList(vender.getDynamicProperty("coin_amount"))
    for (let i = 0; i < coinsList.length ; i++)
    {
        if(coinsList[i]!=0)
            inv.addItem(new ItemStack(coinIdList[i], coinsList[i]))
    }
    vender.setDynamicProperty("coin_amount",0)
}

function PriceCalculator(coins)
{
    const coinsString = String(coins)
    var type = 0
    var coinAmount =0
    if(coinsString.length<=6)
    {
        type=coinsString.length-1
        coinAmount = Number(coinsString[0])
    }
    else
    {
        type=coinList.length-1
        coinAmount = Number(coinsString.slice(0,coinsString.length-6))
    }
        
    return [coinAmount,type]
    
}
function CoinNumberToList(coins) // [copper,tin,...,netherite,void]
{
    const result =[]
    const coinsString = String(coins)
    for(let i = 0; i < coinIdList.length-1 ; i++)
    {
        result.push(Number(coinsString.charAt(coinsString.length-1-i)))
    }
    if(coinsString.slice(0,coinsString.length - coinIdList.length+1) !=" " && coinsString.length >= coinIdList.length)
    {
        result.push(Number(coinsString.slice(0,coinsString.length - coinIdList.length+1)))
    }
    else
        result.push(0)
    return result
}
function CoinNumberToString(coins)
{
    return CoinListToString(CoinNumberToList(coins))
}
function CoinListToString(coins)
{
    var result =""
    for(let i = 1; i <= coinList.length ; i++)
    {
        if(coins[coinList.length-i]!=0)
            result += coins[coinList.length-i] +" "+ coinList[coinList.length-i]+ " "
    }
    if (result=="")
        return "0 "+ coinList[0]
    return result
}
function CoinListToNumber(coins)
{
    var result =0
    for(let i = 0; i < coinIdList.length ; i++)
    {
        result += coins[i]*10**(i)
    }
    return result
}

function VenderAddEasterEgg(item,player)
{
    switch (item.typeId) {
    case "edx:personal_vender":
        world.sendMessage(`§s${player.name} has just committed Vender trafficking`);
        break;
    case "edx:blood_vial":
        player.sendMessage(`§sHopefully this object don't consume blood to run`);
        break;
}
}

function VenderRemoveConfirm(player,vender,item)
{
    var form = new ActionFormData()
    form.title("Personal Vender")
    form.body("Ares you sure you want to remove this vender")
    form.button("§aConfirm")
    form.button("§cCancel")
    form.show(player).then(result => {
        if (result.selection === 0) {
            VenderRemove(player,vender)
        }
    })
}
function VenderRemove(player,vender)
{
    WithdrawVenderItem(player,vender)
    WithdrawCoins(player,vender)
    let inv = player.getComponent("inventory").container
    inv.addItem(new ItemStack('edx:personal_vender', 1))
    vender.remove()
    player.sendMessage(`§bThe vender has been succesfully removed`);
    player.playSound('random.levelup');

}



//trade
export function VenderTradeOpen(player,vender)
{
    var form = new ActionFormData()
    form.title(vender.getDynamicProperty("owner") +" Vender's")
    form.body(GenerateVenderTrades(vender))
    form.button("Buy")
    form.show(player).then(result => {
        if (result.selection === 0) {
            VenderBuyMenu(player,vender)
        }
    })
}

function GenerateVenderTrades(vender)
{
    const [venderPrice,venderCoinType] = PriceCalculator(vender.getDynamicProperty("price"))
    return {rawtext: [{text: "§eCurrently selling:§r "} , {text: vender.getDynamicProperty("item_name")} , {text:" ("} , {text:vender.getDynamicProperty("item_id")} , {text:")\n"},
            {text: "§ePrice per unit:§r "} , {text: venderPrice.toString()} , {text:" "} , {text: coinList[venderCoinType].toString()} , {text:"\n"},
            {text: "§eLeft amount:§r "} , {text: vender.getDynamicProperty("item_amount").toString()} , {text:"\n\n"},
            {text:vender.getDynamicProperty("welcome_text")}]}

}
function GenerateVenderBuyConfirm(vender,amount)
{
    const [venderPrice,venderCoinType] = PriceCalculator(vender.getDynamicProperty("price"))
    const amountPriceText = CoinNumberToString(amount * vender.getDynamicProperty("price"))
    
    return {rawtext: [{text: "§eItem:§r "} , {text: vender.getDynamicProperty("item_name")} , {text:" ("} , {text:vender.getDynamicProperty("item_id")} , {text:")\n"},
        {text: "§ePrice per unit:§r "} , {text: venderPrice.toString()} , {text:" "} , {text: coinList[venderCoinType].toString()} , {text:"\n"},
        {text: "§ePrice for "} , {text: amount.toString()} , {text:":§r "}, {text: amountPriceText} , {text:"\n"}]}
}



function VenderBuyMenu(player,vender)
{
    let form = new ModalFormData()
    form.title(vender.getDynamicProperty("owner") +" Vender's");
    form.slider("Amount", 1, vender.getDynamicProperty("item_amount"),{valueStep:1})
    form.show(player).then(r => {
        // This will stop the code when the player closes the form
        if (r.canceled) return;
    
        // This will assign every input their own variable
        let [ amount ] = r.formValues;
        VenderBuyConfirmMenu(player,vender,amount)
    })
}

function VenderBuyConfirmMenu(player,vender,amount)
{
    var form = new ActionFormData()
    form.title(vender.getDynamicProperty("owner") +" Vender's")
    form.body(GenerateVenderBuyConfirm(vender,amount))
    form.button("§aConfirm")
    form.button("§cCancel")
    form.show(player).then(result => {
        if (result.selection === 0) {
            VenderBuyConfirm(player,vender,amount)
        }
    })
}

function VenderBuyConfirm(player,vender,amount)
{
    const price = amount * vender.getDynamicProperty("price")
    const playerMoney = GetPlayerMoney(player)
    if(CheckIfEnoughMoney(player,playerMoney,price))
    {
        if(vender.getDynamicProperty("item_amount")>=amount)
        {
            RemovePlayerMoney(player,playerMoney,price)
            GivePlayerItem(player,vender,amount)
            RemoveVenderXItems(vender,amount)
            vender.setDynamicProperty("coin_amount",vender.getDynamicProperty("coin_amount")+price)
            player.playSound('random.levelup');
        }
        else
        {
            player.sendMessage("§cAn error occured, this vender can't sell items ");
        }

    }
}

function CheckIfEnoughMoney(player,playerMoney,price)
{
    if(playerMoney<price)
    {
        SendPoorMessage(player)
        return false
    }
    else
        return true
}

function GetPlayerMoney(player)
{
    var result = 0
    let inv = player.getComponent("inventory").container
    for (var i=0;i<36;i++){
        var item=inv.getItem(i);
        if(item!=undefined)
        {
            if(item.getTags()?.includes("coin"))
            {
                result += item.amount*10**coinIdList.indexOf(item.typeId)
            }
        }
      }
    
    return result
}

function SendPoorMessage(player)
{
    const random = Math.random()
    if(random>0.1)
    {
        player.sendMessage("§cYou don't have enough money");
    }
    else
    {
        player.sendMessage("§cYou're too poor to buy this");
    }
}

function RemoveVenderXItems(vender,amount)
{
    vender.setDynamicProperty("item_amount",vender.getDynamicProperty("item_amount")-amount)
    if(vender.getDynamicProperty("item_amount")==0)
        RemoveVenderItem(vender)
}

function GivePlayerItem(player,vender,amount)
{
    if(GetVenderItem(vender)!=undefined)
    {
        
        const venderItem = GetVenderItem(vender).clone()
        for (let i = 1; i <= amount ; i++) {
            player.dimension.spawnItem(venderItem, player.location);
        }
    }
    else
    {
        player.sendMessage("§cAn error occured, this vender can't sell items ");
    }
}

function RemovePlayerMoney(player,playerMoney,price)
{
    if(price==0)return;
    const change = playerMoney - price
    const changeList = CoinNumberToList(change)
    let inv = player.getComponent("inventory").container
    for (var i=0;i<36;i++){
        var item=inv.getItem(i);
        if(item!=undefined)
        {
            if(item.getTags()?.includes("coin"))
            {
                inv.setItem(i, undefined)
            }
        }
    }
    console.warn(playerMoney)
    console.warn(price)
    console.warn(change)
    if(change<=0) return;
    for (let i = 0; i < changeList.length ; i++)
    {
        if(changeList[i]!=0)
            inv.addItem(new ItemStack(coinIdList[i], changeList[i]))
    }
}

function TestClose(vender,player=undefined)
{
    if((vender.getDynamicProperty("item_amount")<=0 || ["edx:boredom","minecraft:air"].includes(vender.getDynamicProperty("item_type"))) && vender.getProperty("edx:open")==true)
    {
        vender.setProperty("edx:open",false);
        if(player!=undefined)
        {
            player.sendMessage("§cThis vender can't be open because it doesn't sell anythnig");
        }
    }
}