contract Main is MainChip,MainCard,MainBag,MainBonus
{
    using ItemList for ItemList.Data;

    constructor(address Receiver) public MainBonus(Receiver) {}

    ///==================================================================
    bool g_Synced = false;
    function SyncOldData(OldMain oldMain, address[] accounts) external CreatorAble
    {
        // transfer itemdata
        require(!g_Synced);
        g_Synced = true;
        for (uint i=0; i<accounts.length; i++)
        {
            address acc = accounts[i];
            SyncStuff(oldMain, acc);
            SyncTempStuff(oldMain, acc);
            SyncChip(oldMain, acc);
            SyncCard(oldMain, acc);
        }
    }

    function SyncItemData(ItemList.Data storage Data, uint32[] idxList, uint[] valList) internal
    {
        if (idxList.length == 0) return;
        for (uint i=0; i<idxList.length; i++)
        {
            uint32 index = idxList[i];
            uint val = valList[i];
            Data.set(index, val);
        }
    }

    function SyncStuff(OldMain oldMain, address acc) internal
    {
        (uint32[] memory idxList, uint[] memory valList) = oldMain.GetStuffList(acc);
        SyncItemData(g_BagList[acc].m_Stuff, idxList, valList);
    }

    function SyncTempStuff(OldMain oldMain, address acc) internal
    {
        (uint32[] memory idxList, uint[] memory valList) = oldMain.GetTempStuffList(acc);
        SyncItemData(g_BagList[acc].m_TempStuff, idxList, valList);
    }

    function SyncChip(OldMain oldMain, address acc) internal
    {
        (uint32[] memory idxList, uint[] memory valList) = oldMain.GetChipList(acc);
        SyncItemData(g_BagList[acc].m_Chips, idxList, valList);
    }

    function CompensateChips(address acc, uint32[] idxList) internal
    {
        for (uint i=0; i<idxList.length; i++)
        {
            uint32 iCard = idxList[i];
            if (iCard == 0) return;
            Card storage obj = GetCard(iCard);
            for (uint j=0; j<obj.m_Parts.length; j++)
            {
                uint32 iChip = obj.m_Parts[j];
                g_BagList[acc].m_Chips.add(iChip,1);
            }
        }
    }

    function SyncCard(OldMain oldMain, address acc) internal
    {
        (uint32[] memory idxList, uint[] memory valList ,uint32[] memory permCards) = oldMain.GetCardList(acc);
        uint32[] memory allCards = new uint32[](idxList.length+permCards.length);
        uint i=0;
        uint j=0;
        for (j=0; j<idxList.length; j++)
        {
            uint expire = valList[j];
            if (expire < now) continue;
            allCards[i] = idxList[j];
            i++;
        }
        for (j=0; j<permCards.length; j++)
        {
            allCards[i] = permCards[j];
            i++;
        }
        CompensateChips(acc, allCards);
    }

    ///==================================================================

    function InsertCard(uint32 iCard, uint32 duration, uint8 level, uint16 dp, uint16 dpk, uint16 sp, uint16 ip, uint32[] parts) external CreatorAble
    {
        require(!CardExists(iCard));
        require(level<=HEROLEVEL_MAX && level>=HEROLEVEL_MIN);
        require(GetPartNum(level) == parts.length);
        AddNewCard(iCard, duration, level, dp, dpk, sp, ip, parts);
        for (uint8 iPart=1; iPart<=parts.length; iPart++)
        {
            uint idx = iPart-1;
            uint32 iChip = parts[idx];
            uint8 limit = GetPartLimit(level, iPart);
            AddNewChip(iChip, level, limit, iPart);
        }
    }

    function GainCard(address acc, uint32 iCard) external AuthAble OwnerAble(acc)
    {
        require(CardExists(iCard) && !HasCard(acc,iCard));
        GainCard2(acc,iCard);
        ProfitByCard(acc,iCard);
    }

    function GetDynamicCardAmountList(address acc) external view returns(uint[] amountList)
    {
        Bag storage oBag = g_BagList[acc];
        uint len = oBag.m_TempCards.m_List.length;
        amountList = new uint[](len);
        for (uint i=0; i<len; i++)
        {
            uint32 iCard = oBag.m_TempCards.m_List[i];
            amountList[i] = GetDynamicCardNum(iCard,GetDayCount(now));
        }
    }

    function GenChipByRandomWeight(uint random, uint8 level, uint[] extWeight) external AuthAble returns(uint32 iChip)
    {
        RefreshChipUnableList(level);
        iChip = GenChipByWeight(random,level,extWeight);
        ObtainChip(iChip);
    }

    function CheckGenChip(uint32 iChip) external view returns(bool)
    {
        return CanObtainChip(iChip);
    }

    function GenChip(uint32 iChip) external AuthAble
    {
        require(CanObtainChip(iChip));
        ObtainChip(iChip);
    }

}
function InsertCard(uint32 iCard, uint32 duration, uint8 level, uint16 dp, uint16 dpk, uint16 sp, uint16 ip, uint32[] parts) external CreatorAble
{
    require(!CardExists(iCard));
    require(level<=HEROLEVEL_MAX && level>=HEROLEVEL_MIN);
    require(GetPartNum(level) == parts.length);
    AddNewCard(iCard, duration, level, dp, dpk, sp, ip, parts);
    for (uint8 iPart=1; iPart<=parts.length; iPart++)
    {
        uint idx = iPart-1;
        uint32 iChip = parts[idx];
        uint8 limit = GetPartLimit(level, iPart);
        AddNewChip(iChip, level, limit, iPart);
    }
}

///==================================================================