contract LoanToValueDebtAggregator is Ownable, ILoanToValueAggregator {
	string private _name;

	FaceValueDebt[] private _trackedTokens;

	int256 private _f_appraisedCapitalValue = 0;
	int256 private _f_offChainLoanValue = 0;

	constructor(string memory name, uint256 appriasedCapitalValue, uint256 offChainLoanValue)
		public
	{
		setAppraisedCapitalValue(appriasedCapitalValue);
		setOffChainLoanValue(offChainLoanValue);
		_name = name;
	}

	function name() public view returns (string memory) {
		return _name;
	}

	function setAppraisedCapitalValue(uint256 value) public onlyOwner {
		_f_appraisedCapitalValue = int256(value).newFixed();
	}

	function getFixedAppraisedCapitalValue() public view returns (int256) {
		return _f_appraisedCapitalValue;
	}

	function setOffChainLoanValue(uint256 offChainLoanValue) public onlyOwner {
		_f_offChainLoanValue = int256(offChainLoanValue).newFixed();
	}

	function getFixedOffChainLoanValue() public view returns (int256) {
		return _f_offChainLoanValue;
	}

	function getFixedOnChainLoanValue() public view returns (int256) {
		require(_trackedTokens.length > 0, "No tracked tokens");
		int256 f_onChainLoanValue = int256(0).newFixed();
		for (uint256 i = 0; i < _trackedTokens.length; i++) {
			f_onChainLoanValue = f_onChainLoanValue.add(
				_trackedTokens[i].getFixedInitialValue().multiply(
					int256(_trackedTokens[i].totalSupply()).newFixed()
				)
			);
		}
		return f_onChainLoanValue;
	}

	function calculateFixedLtV() public view returns (int256) {
		require(_f_appraisedCapitalValue != 0, "Appraised Capital value = 0");
		int256 f_loanAmmount = _f_offChainLoanValue + getFixedOnChainLoanValue();
		return f_loanAmmount.divide(_f_appraisedCapitalValue);
	}

	function getFixedTokenisedRatio() public view returns (int256) {
		return
			_f_offChainLoanValue.add(getFixedOnChainLoanValue()).divide(_f_appraisedCapitalValue);
	}

	function addToken(address tokenAddr) public onlyOwner {
		_trackedTokens.push(FaceValueDebt(tokenAddr));
	}

	function removeToken(address tokenAddr) public onlyOwner {
		require(_trackedTokens.length > 0, "No tokens tracked by this aggregator.");
		uint256 i = 0;
		if (_trackedTokens.length != 1) {
			i = findTokenIndexByAddress(tokenAddr);
		}
		if (i != _trackedTokens.length - 1) {
			// If not in last position, overwrite deleted token with last token
			_trackedTokens[i] = _trackedTokens[_trackedTokens.length - 1];
		}
		_trackedTokens.pop();
	}

	function findTokenIndexByAddress(address tokenAddr) private view returns (uint256) {
		for (uint256 i = 0; i < _trackedTokens.length; i++) {
			if (address(_trackedTokens[i]) == tokenAddr) {
				return i;
			}
		}
		revert("Token not found.");
	}

	function fixedDecimalDigits() public pure returns (int256) {
		return FixidityLib.digits();
	}

	/**
    * @dev Destroy the contract
    */
	function Destroy() public onlyOwner returns (bool) {
		selfdestruct(msg.sender);
		return true;
	}
}
function Destroy() public onlyOwner returns (bool) {
	selfdestruct(msg.sender);
	return true;
}

/**
 * @dev Destroy the contract
 */