library LibStructs{
    using Serializer for Serializer.DataComponent;
    // HEROES

    struct Hero {
        uint16 stockID;
        uint8 rarity;
        uint16 hp;
        uint16 atk;
        uint16 def;
        uint16 agi;
        uint16 intel;
        uint16 cHp;
        //uint8 cenas;
        // uint8 critic;
        // uint8 healbonus;
        // uint8 atackbonus;
        // uint8 defensebonus;

        uint8 isForSale;
        uint8 lvl;
        uint16 xp;
    }
    struct StockHero {uint16 price;uint8 stars;uint8 mainOnePosition;uint8 mainTwoPosition;uint16 stock;uint8 class;}

    function SerializeHero(Hero hero) internal pure returns (bytes32){
        Serializer.DataComponent memory data;
        data.WriteUint16(0, hero.stockID);
        data.WriteUint8(2, hero.rarity);
        //data.WriteUint8(2, hero.m_IsForSale);
        //data.WriteUint8(3, rocket.m_Unused3);
        data.WriteUint16(4, hero.hp);
        data.WriteUint16(6, hero.atk);
        data.WriteUint16(8, hero.def);
        data.WriteUint16(10, hero.agi);
        data.WriteUint16(12, hero.intel);
        data.WriteUint16(14, hero.cHp);

        // data.WriteUint8(16, hero.class);
        // data.WriteUint8(17, hero.healbonus);
        // data.WriteUint8(18, hero.atackbonus);
        // data.WriteUint8(19, hero.defensebonus);

        data.WriteUint8(20, hero.isForSale);
        data.WriteUint8(21, hero.lvl);
        data.WriteUint16(23, hero.xp);

        return data.m_Raw;
    }
    function DeserializeHero(bytes32 raw) internal pure returns (Hero){
        Hero memory hero;

        Serializer.DataComponent memory data;
        data.m_Raw = raw;

        hero.stockID = data.ReadUint16(0);
        //hero.rarity = data.ReadUint8(1);
        hero.rarity = data.ReadUint8(2);
        //rocket.m_Unused3 = data.ReadUint8(3);
        hero.hp = data.ReadUint16(4);
        hero.atk = data.ReadUint16(6);
        hero.def = data.ReadUint16(8);
        hero.agi = data.ReadUint16(10);
        hero.intel = data.ReadUint16(12);
        hero.cHp = data.ReadUint16(14);

        // hero.class = data.ReadUint8(16);
        // hero.healbonus = data.ReadUint8(17);
        // hero.atackbonus = data.ReadUint8(18);
        // hero.defensebonus = data.ReadUint8(19);

        hero.isForSale = data.ReadUint8(20);
        hero.lvl = data.ReadUint8(21);
        hero.xp = data.ReadUint16(23);

        return hero;
    }
    function SerializeStockHero(StockHero stockhero) internal pure returns (bytes32){
        // string name;uint64 price;uint8 stars;uint8 mainOnePosition;uint8 mainTwoPosition;

        Serializer.DataComponent memory data;
        data.WriteUint16(0, stockhero.price);
        data.WriteUint8(2, stockhero.stars);
        data.WriteUint8(3, stockhero.mainOnePosition);
        data.WriteUint8(4, stockhero.mainTwoPosition);
        data.WriteUint16(5, stockhero.stock);
        data.WriteUint8(7, stockhero.class);


        return data.m_Raw;
    }
    function DeserializeStockHero(bytes32 raw) internal pure returns (StockHero){
        StockHero memory stockhero;

        Serializer.DataComponent memory data;
        data.m_Raw = raw;

        stockhero.price = data.ReadUint16(0);
        stockhero.stars = data.ReadUint8(2);
        stockhero.mainOnePosition = data.ReadUint8(3);
        stockhero.mainTwoPosition = data.ReadUint8(4);
        stockhero.stock = data.ReadUint16(5);
        stockhero.class = data.ReadUint8(7);

        return stockhero;
    }
    // ITEMS
    struct Item {
        uint16 stockID;
        uint8 lvl;
        uint8 rarity;
        uint16 hp;
        uint16 atk;
        uint16 def;
        uint16 agi;
        uint16 intel;

        uint8 critic;
        uint8 healbonus;
        uint8 atackbonus;
        uint8 defensebonus;

        uint8 isForSale;
        uint8 grade;
    }
    struct StockItem {uint16 price;uint8 stars;uint8 lvl;uint8 mainOnePosition;uint8 mainTwoPosition;uint16[5] stats;uint8[4] secstats;uint8 cat;uint8 subcat;} // 1 finney = 0.0001 ether

    function SerializeItem(Item item) internal pure returns (bytes32){
        Serializer.DataComponent memory data;

        data.WriteUint16(0, item.stockID);
        data.WriteUint8(4, item.lvl);
        data.WriteUint8(5, item.rarity);
        data.WriteUint16(6, item.hp);
        data.WriteUint16(8, item.atk);
        data.WriteUint16(10, item.def);
        data.WriteUint16(12, item.agi);
        data.WriteUint16(14, item.intel);
        // data.WriteUint32(14, item.cHp);

        data.WriteUint8(16, item.critic);
        data.WriteUint8(17, item.healbonus);
        data.WriteUint8(18, item.atackbonus);
        data.WriteUint8(19, item.defensebonus);

        data.WriteUint8(20, item.isForSale);
        data.WriteUint8(21, item.grade);


        return data.m_Raw;

    }
    function DeserializeItem(bytes32 raw) internal pure returns (Item){
        Item memory item;

        Serializer.DataComponent memory data;
        data.m_Raw = raw;

        item.stockID = data.ReadUint16(0);

        item.lvl = data.ReadUint8(4);
        item.rarity = data.ReadUint8(5);
        item.hp = data.ReadUint16(6);
        item.atk = data.ReadUint16(8);
        item.def = data.ReadUint16(10);
        item.agi = data.ReadUint16(12);
        item.intel = data.ReadUint16(14);

        item.critic = data.ReadUint8(16);
        item.healbonus = data.ReadUint8(17);
        item.atackbonus = data.ReadUint8(18);
        item.defensebonus = data.ReadUint8(19);

        item.isForSale = data.ReadUint8(20);
        item.grade = data.ReadUint8(21);


        return item;
    }
    function SerializeStockItem(StockItem stockitem) internal pure returns (bytes32){
        // string name;uint64 price;uint8 stars;uint8 mainOnePosition;uint8 mainTwoPosition;uint8 mainThreePosition;
        // uint16[] stats;uint8[] secstats;

        Serializer.DataComponent memory data;
        data.WriteUint16(0, stockitem.price);
        data.WriteUint8(2, stockitem.stars);
        data.WriteUint8(3, stockitem.lvl);
        data.WriteUint8(4, stockitem.mainOnePosition);
        data.WriteUint8(5, stockitem.mainTwoPosition);
        //data.WriteUint8(12, stockitem.mainThreePosition);
        //stats
        data.WriteUint16(6, stockitem.stats[0]);
        data.WriteUint16(8, stockitem.stats[1]);
        data.WriteUint16(10, stockitem.stats[2]);
        data.WriteUint16(12, stockitem.stats[3]);
        data.WriteUint16(14, stockitem.stats[4]);
        //secstats
        data.WriteUint8(16, stockitem.secstats[0]);
        data.WriteUint8(17, stockitem.secstats[1]);
        data.WriteUint8(18, stockitem.secstats[2]);
        data.WriteUint8(19, stockitem.secstats[3]);

        data.WriteUint8(20, stockitem.cat);
        data.WriteUint8(21, stockitem.subcat);


        return data.m_Raw;
    }
    function DeserializeStockItem(bytes32 raw) internal pure returns (StockItem){
        StockItem memory stockitem;

        Serializer.DataComponent memory data;
        data.m_Raw = raw;

        stockitem.price = data.ReadUint16(0);
        stockitem.stars = data.ReadUint8(2);
        stockitem.lvl = data.ReadUint8(3);
        stockitem.mainOnePosition = data.ReadUint8(4);
        stockitem.mainTwoPosition = data.ReadUint8(5);
        //stockitem.mainThreePosition = data.ReadUint8(12);

        stockitem.stats[0] = data.ReadUint16(6);
        stockitem.stats[1] = data.ReadUint16(8);
        stockitem.stats[2] = data.ReadUint16(10);
        stockitem.stats[3] = data.ReadUint16(12);
        stockitem.stats[4] = data.ReadUint16(14);

        stockitem.secstats[0] = data.ReadUint8(16);
        stockitem.secstats[1] = data.ReadUint8(17);
        stockitem.secstats[2] = data.ReadUint8(18);
        stockitem.secstats[3] = data.ReadUint8(19);

        stockitem.cat = data.ReadUint8(20);
        stockitem.subcat = data.ReadUint8(21);

        return stockitem;
    }

    struct Action {uint16 actionID;uint8 actionType;uint16 finneyCost;uint32 cooldown;uint8 lvl;uint8 looted;uint8 isDaily;}
    function SerializeAction(Action action) internal pure returns (bytes32){
        Serializer.DataComponent memory data;
        data.WriteUint16(0, action.actionID);
        data.WriteUint8(2, action.actionType);
        data.WriteUint16(3, action.finneyCost);
        data.WriteUint32(5, action.cooldown);
        data.WriteUint8(9, action.lvl);
        data.WriteUint8(10, action.looted);
        data.WriteUint8(11, action.isDaily);

        return data.m_Raw;
    }
    function DeserializeAction(bytes32 raw) internal pure returns (Action){
        Action memory action;

        Serializer.DataComponent memory data;
        data.m_Raw = raw;

        action.actionID = data.ReadUint16(0);
        action.actionType = data.ReadUint8(2);
        action.finneyCost = data.ReadUint16(3);
        action.cooldown = data.ReadUint32(5);
        action.lvl = data.ReadUint8(9);
        action.looted = data.ReadUint8(10);
        action.isDaily = data.ReadUint8(11);

        return action;
    }

    struct Mission {uint8 dificulty;uint16[4] stockitemId_drops;uint16[5] statsrequired;uint16 count;}
    function SerializeMission(Mission mission) internal pure returns (bytes32){
        Serializer.DataComponent memory data;
        data.WriteUint8(0, mission.dificulty);
        data.WriteUint16(1, mission.stockitemId_drops[0]);
        data.WriteUint16(5, mission.stockitemId_drops[1]);
        data.WriteUint16(9, mission.stockitemId_drops[2]);
        data.WriteUint16(13, mission.stockitemId_drops[3]);

        data.WriteUint16(15, mission.statsrequired[0]);
        data.WriteUint16(17, mission.statsrequired[1]);
        data.WriteUint16(19, mission.statsrequired[2]);
        data.WriteUint16(21, mission.statsrequired[3]);
        data.WriteUint16(23, mission.statsrequired[4]);

        data.WriteUint16(25, mission.count);

        return data.m_Raw;
    }
    function DeserializeMission(bytes32 raw) internal pure returns (Mission){
        Mission memory mission;

        Serializer.DataComponent memory data;
        data.m_Raw = raw;

        mission.dificulty = data.ReadUint8(0);
        mission.stockitemId_drops[0] = data.ReadUint16(1);
        mission.stockitemId_drops[1] = data.ReadUint16(5);
        mission.stockitemId_drops[2] = data.ReadUint16(9);
        mission.stockitemId_drops[3] = data.ReadUint16(13);

        mission.statsrequired[0] = data.ReadUint16(15);
        mission.statsrequired[1] = data.ReadUint16(17);
        mission.statsrequired[2] = data.ReadUint16(19);
        mission.statsrequired[3] = data.ReadUint16(21);
        mission.statsrequired[4] = data.ReadUint16(23);

        mission.count = data.ReadUint16(25);

        return mission;
    }

    function toWei(uint80 price) public returns(uint256 value){
        value = price;
        value = value * 1 finney;

    }

}
function SerializeItem(Item item) internal pure returns (bytes32){
    Serializer.DataComponent memory data;

    data.WriteUint16(0, item.stockID);
    data.WriteUint8(4, item.lvl);
    data.WriteUint8(5, item.rarity);
    data.WriteUint16(6, item.hp);
    data.WriteUint16(8, item.atk);
    data.WriteUint16(10, item.def);
    data.WriteUint16(12, item.agi);
    data.WriteUint16(14, item.intel);
    // data.WriteUint32(14, item.cHp);

    data.WriteUint8(16, item.critic);
    data.WriteUint8(17, item.healbonus);
    data.WriteUint8(18, item.atackbonus);
    data.WriteUint8(19, item.defensebonus);

    data.WriteUint8(20, item.isForSale);
    data.WriteUint8(21, item.grade);


    return data.m_Raw;

}

// 1 finney = 0.0001 ether