using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;
using TMPro;

public class TradeMenu : MonoBehaviour
{
    public Transform tradeListParent;
    public GameObject tradeListItem;
    public Button refreshIndicator;
    public TMP_Text coinsTxt;
    public TMP_Text gemsTxt;
    public List<GameObject> pooledEntries;
    public List<TradeRequest> trades;
    [Header("Selected Trade Data")]
    public TradeRequest selectedTrade = null;
    public TMP_Text sellerNameTxt;
    public GameObject coinsItem;
    public GameObject gemsItem;
    public GameObject metalsItem;
    public GameObject oxygenItem;
    public Image itemImg;
    public Sprite defaultFrame;
    public Sprite mineFrame;
    public Button acceptBtn;
    void Start()
    {
        pooledEntries = new List<GameObject>();
        //pooledEntries.Add(tradeListItem);
        refreshIndicator.onClick.AddListener(Refresh);
        acceptBtn.onClick.AddListener(OnAcceptClicked);
        Refresh();
    }

    // Update is called once per frame
    void Update()
    {

    }

    public bool refreshing = false;
    public async void Refresh()
    {
        refreshing = true;
        refreshIndicator.interactable=false;
        refreshIndicator.GetComponent<Rotator>().enabled = (true);
        //Clean existing entries
        foreach (GameObject entry in pooledEntries) { entry.SetActive(false); }
        coinsTxt.text = DBmanager.Coins.ToString();
        gemsTxt.text = DBmanager.Gems.ToString();
        selectedTrade = null;
        //  if(selectedTrade==null){
        coinsItem.SetActive(false);
        gemsItem.SetActive(false);
        metalsItem.SetActive(false);
        oxygenItem.SetActive(false);
        acceptBtn.interactable = false;
        itemImg.sprite = null;
        //}

        using (UnityWebRequest www = UnityWebRequest.Get(DBmanager.phpRoot + "get_trades.php"))
        {
            var operation = www.SendWebRequest();
            while (!operation.isDone)
            {
                await Task.Yield();
            }

            if (www.downloadHandler.text.ToLower().Contains("0 results"))
            {
                Debug.Log("No trade requests for now");
            }
            else
            {
                string[] splitChars = { "<td>" };
                string[] data = www.downloadHandler.text.Split(splitChars, System.StringSplitOptions.RemoveEmptyEntries);
                trades = new List<TradeRequest>();
                foreach (string row in data)
                {
                    try
                    {
                        TradeRequest trade = JsonConvert.DeserializeObject<TradeRequest>(row);
                        trades.Add(trade);
                        if(trade.seller == DBmanager.username){
                            trades[trades.Count-1] = trades[0];
                            trades[0] = trade;
                        }
                    }
                    catch
                    {

                    }
                }

                Debug.Log($"Added {trades.Count} trades from {data.Length} entries");
            }
        }

        //Populate Trade Entries in list


        //Fill pool if exceeds
        int amountToFill = trades.Count - pooledEntries.Count;
        if (amountToFill > 0)
        {
            for (int i = 0; i < amountToFill; i++)
            {
                GameObject newEntry = Instantiate(tradeListItem, tradeListParent);
                newEntry.SetActive(false);
                pooledEntries.Add(newEntry);
            }
        }
        if(trades.Count > pooledEntries.Count){Debug.LogError("Somethings wrong, I can feel it");}
        //Set pooled items
        for (int i = 0; i < trades.Count; i++)
        {
            TradeRequest trade = trades[i];
            InventoryItem item = Inventory.GetInventoryItem(trade.item);
            if (item == null) { Debug.LogError("Couldn't find any inventory item for " + trade.item); continue; }
            pooledEntries[i].SetActive(true);
            pooledEntries[i].transform.GetChild(0).GetComponent<Image>().sprite = item.image;
            pooledEntries[i].GetComponentInChildren<TMPro.TMP_Text>().text = trade.item;
            pooledEntries[i].GetComponent<Button>().onClick.RemoveAllListeners();
            pooledEntries[i].GetComponent<Button>().onClick.AddListener(() => { SelectTrade(trade.id); });

            pooledEntries[i].GetComponent<Image>().sprite = (trade.seller == DBmanager.username) ? mineFrame : defaultFrame;

        }

refreshIndicator.interactable=true;
        refreshIndicator.GetComponentInChildren<Rotator>(true).enabled=(false);
        
        refreshing = false;
    }

    public void SelectTrade(TradeRequest trade)
    {
        SelectTrade(trade.id);
    }

    public void SelectTrade(int id)
    {
        selectedTrade = null;
        foreach (TradeRequest trade in trades)
        {
            if (trade.id == id)
            {
                selectedTrade = trade;
                break;
            }
        }
        if (selectedTrade == null) { Debug.Log("No matching trade request"); return; }
        bool myTrade = selectedTrade.seller == DBmanager.username;
        InventoryItem item = Inventory.GetInventoryItem(selectedTrade.item);
        itemImg.sprite = item.image;

        #region setResource
        if (selectedTrade.coins > 0)
        {
            coinsItem.SetActive(true);
            coinsItem.GetComponentInChildren<TMP_Text>().text = selectedTrade.coins.ToString();
        }
        else
        {
            coinsItem.SetActive(false);
        }

        if (selectedTrade.gems > 0)
        {
            gemsItem.SetActive(true);
            gemsItem.GetComponentInChildren<TMP_Text>().text = selectedTrade.gems.ToString();
        }
        else
        {
            gemsItem.SetActive(false);
        }

        if (selectedTrade.metals > 0)
        {
            metalsItem.SetActive(true);
            metalsItem.GetComponentInChildren<TMP_Text>().text = selectedTrade.metals.ToString();
        }
        else
        {
            metalsItem.SetActive(false);
        }

        if (selectedTrade.oxygen > 0)
        {
            oxygenItem.SetActive(true);
            oxygenItem.GetComponentInChildren<TMP_Text>().text = selectedTrade.oxygen.ToString();
        }
        else
        {
            oxygenItem.SetActive(false);
        }
        #endregion

        sellerNameTxt.text = selectedTrade.seller;

        acceptBtn.interactable = !myTrade && isTradeAffordable(selectedTrade);
    }

    public bool isTradeAffordable(TradeRequest trade) => (DBmanager.Coins >= trade.coins) && (DBmanager.Gems >= trade.gems) && (DBmanager.Metal >= trade.metals) && (DBmanager.Oxygen >= trade.oxygen);

    public void OnAcceptClicked(){
        if(selectedTrade==null){Debug.Log("No offer is selected to accept"); return;}
        if(selectedTrade.seller == DBmanager.username){Debug.LogError("Cannot accept my own offer, This is illegal"); return;}
        if(!isTradeAffordable(selectedTrade)){Debug.Log("Insufficient resources to complete the trade (LC)");return;}

        //Good to go
        StartCoroutine(acceptOffer(selectedTrade));
    }

    IEnumerator acceptOffer(TradeRequest trade){
        acceptBtn.interactable=false;
        WWWForm form = new WWWForm();
        form.AddField("name", DBmanager.username);
        form.AddField("id", trade.id);

        WWW www = new WWW(DBmanager.phpRoot+"accept_trade.php", form);
        yield return www;

        if(www.text=="0"){
            Debug.Log("Trade success");
            //change local stuff
            DBmanager.SetCoins(DBmanager.Coins - trade.coins,true);
            DBmanager.SetGems(DBmanager.Gems -  trade.gems,true);
            DBmanager.SetOxygen(DBmanager.Oxygen - trade.oxygen,true);
            DBmanager.SetMetal(DBmanager.Metal - trade.metals, true);
            DBmanager.AddInventoryItem(Inventory.GetInventoryItem(trade.item));
            Refresh();
        }else{
            Debug.Log($"I wanted to trade, but server said :{www.text}");
        }
        acceptBtn.interactable=true;
    }


    public void Show()
    {
        gameObject.SetActive(true);
        Refresh();
    }

    public void Close()
    {
        gameObject.SetActive(false);
    }
}


[System.Serializable]
public class TradeRequest
{
    public int id;
    public string seller;
    public string item;
    public int coins;
    public int gems;
    public int metals;
    public int oxygen;
}
