contract MifflinMarket is Owned {
    mapping(uint8 => address) public tokenIds;
    //mapping(uint8 => mapping(uint8 => uint256)) exchangeRates;
    mapping(uint8 => mapping(uint8 => int256)) public totalExchanged;
    uint8 rewardTokenId = 1;
    bool active;
    
     function MifflinMarket() public {
         active = true;
     }
    
     modifier onlyTokens {
        MifflinToken mt = MifflinToken(msg.sender);
        // make sure sender is a token contract
        require(tokenIds[mt.tokenId()] == msg.sender);
        _;
    }

    function setToken(uint8 tid,address addy) public onlyOwnerOrigin { // Only add tokens that were created by exchange owner
        tokenIds[tid] = addy;
    }

    function removeToken(uint8 id) public onlyOwner { // Only add tokens that were created by owner
        tokenIds[id] = 0;
    }
    
    function setActive(bool act) public onlyOwner {
        active = act;
    }

    function getRewardToken() public view returns(MifflinToken){
        return getTokenById(rewardTokenId);
    }

    function getTokenById(uint8 id) public view returns(MifflinToken){
        require(tokenIds[id] > 0);
        return MifflinToken(tokenIds[id]);
    }
    
    function getTokenByAddress(address addy) public view returns(MifflinToken){
        MifflinToken token = MifflinToken(addy);
        uint8 tokenId = token.tokenId();
        require(tokenIds[tokenId] == addy);
        return token;
    }

    function exchangeTokensByAddress(uint256 fromAmount, address from, address to) public {
        require(active);
        uint256 takeAmount = fromAmount;
        MifflinToken fromToken = getTokenByAddress(from);
        MifflinToken toToken = getTokenByAddress(to);
        uint8 fromId = fromToken.tokenId();
        uint8 toId = toToken.tokenId();
        uint256 fromPrice = fromToken.buyPrice();
        uint256 toPrice = toToken.buyPrice();
        uint256 toAmount = fromAmount * fromPrice / toPrice;
        takeAmount = toAmount * toPrice / fromPrice;
        // take fromTokens back to contract
        fromToken.take(msg.sender, takeAmount);
        // give toTokens out from contract
        toToken.give(msg.sender, toAmount);
        // update some stats
        totalExchanged[fromId][toId] += int(toAmount);
        totalExchanged[toId][fromId] -= int(takeAmount);
    }

    // most basic exchange - just calculates price ratio
    function exchangeTokensById(uint256 fromAmount, uint8 from, uint8 to) public {
        address fromAddress = tokenIds[from];
        address toAddress = tokenIds[to];
        exchangeTokensByAddress(fromAmount,fromAddress,toAddress);
	    //adjust price?
    }

    function highContributionAward(address to) public onlyTokens {
        MifflinToken reward = getRewardToken();
        //dont throw an error if there are no more tokens
        if(reward.balanceOf(reward) > 0){
            reward.give(to, 1);
        }
    }

    function lowContributionAward(address to) public onlyTokens {
        MifflinToken reward = getRewardToken();
        //dont throw an error here since this is just sugar
        if(reward.balanceOf(to) > 0){
            reward.take(to, 1);
        }
    }
}
function exchangeTokensById(uint256 fromAmount, uint8 from, uint8 to) public {
    address fromAddress = tokenIds[from];
    address toAddress = tokenIds[to];
    exchangeTokensByAddress(fromAmount,fromAddress,toAddress);
 //adjust price?
}

// most basic exchange - just calculates price ratio