contract ServiceStation is Pausable, ServiceStationBase {

	// @dev Sanity check that allows us to ensure that we are pointing to the right call.
    bool public isServicestation = true;
	
    /// @dev The ERC-165 interface signature for ERC-721.
    ///  Ref: https://github.com/ethereum/EIPs/issues/165
    ///  Ref: https://github.com/ethereum/EIPs/issues/721
    bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d);

    uint256 public optionCount;
    mapping (uint64 => uint256) public modelIndexToOptionCount;
    /// @dev Constructor creates a reference to the NFT ownership contract
    ///  and verifies the owner cut is in the valid range.
    /// @param _nftAddress - address of a deployed contract implementing
    ///  the Nonfungible Interface.
    function ServiceStation(address _nftAddress) public {

        ERC721 candidateContract = ERC721(_nftAddress);
        //require(candidateContract.supportsInterface(InterfaceSignature_ERC721));
        nonFungibleContract = candidateContract;
        _newTuneOption(0,0,0,false,false,0,0);
        
    }
    function setNFTAddress(address _nftAddress) external onlyOwner {
        
        ERC721 candidateContract = ERC721(_nftAddress);
        //require(candidateContract.supportsInterface(InterfaceSignature_ERC721));
        nonFungibleContract = candidateContract;
    }
    
    function newTuneOption(
        uint32 _startChange,
        uint32 _rangeChange,
        uint256 _attChange,
        bool _plusMinus,
        bool _replace,
        uint128 _price,
        uint64 _model
        )
        external
        {
           //Only allow owner to add new options
           require(msg.sender == owner ); 
           optionCount++;
           modelIndexToOptionCount[_model]++;
           _newTuneOption(_startChange,_rangeChange,_attChange,_plusMinus, _replace,_price,_model);
       
        }
    function changeTuneOption(
        uint32 _startChange,
        uint32 _rangeChange,
        uint256 _attChange,
        bool _plusMinus,
        bool _replace,
        uint128 _price,
        bool _isactive,
        uint64 _model,
        uint256 _optionIndex
        )
        external
        {
           //Only allow owner to add new options
           require(msg.sender == owner ); 
           
           
           _changeTuneOption(_startChange,_rangeChange,_attChange,_plusMinus, _replace,_price,_isactive,_model,_optionIndex);
       
        }
        
    function _newTuneOption( uint32 _startChange,
        uint32 _rangeChange,
        uint256 _attChange,
        bool _plusMinus,
        bool _replace,
        uint128 _price,
        uint64 _model
        ) 
        internal
        {
        
           Tune memory _option = Tune({
            startChange: _startChange,
            rangeChange: _rangeChange,
            attChange: _attChange,
            plusMinus: _plusMinus,
            replace: _replace,
            price: _price,
            active: true,
            model: _model
            });
        
        options.push(_option);
    }
    
    function _changeTuneOption( uint32 _startChange,
        uint32 _rangeChange,
        uint256 _attChange,
        bool _plusMinus,
        bool _replace,
        uint128 _price,
        bool _isactive,
        uint64 _model,
        uint256 _optionIndex
        ) 
        internal
        {
        
           Tune memory _option = Tune({
            startChange: _startChange,
            rangeChange: _rangeChange,
            attChange: _attChange,
            plusMinus: _plusMinus,
            replace: _replace,
            price: _price,
            active: _isactive,
            model: _model
            });
        
        options[_optionIndex]=_option;
    }
    
    function disableTuneOption(uint256 index) external
    {
        require(msg.sender == owner ); 
        options[index].active=false;
    }
    
    function enableTuneOption(uint256 index) external
    {
        require(msg.sender == owner ); 
        options[index].active=true;
    }
    function getOption(uint256 _index) 
    external view
    returns (
        uint256 _startChange,
        uint256 _rangeChange,
        uint256 _attChange,
        bool _plusMinus,
        uint128 _price,
        bool active,
        uint64 model
    ) 
    {
      
        //require(options[_index].active);
        return (
            options[_index].startChange,
            options[_index].rangeChange,
            options[_index].attChange,
            options[_index].plusMinus,
            options[_index].price,
            options[_index].active,
            options[_index].model
        );  
    }
    
    function getOptionCount() external view returns (uint256 _optionCount)
        {
        return optionCount;    
        }
    
    function tuneLambo(uint256 _tokenId,uint256 _optionIndex) external payable
    {
       //Caller needs to own Lambo
       require(_owns(msg.sender, _tokenId)); 
       //Tuning Option needs to be enabled
       require(options[_optionIndex].active);
       //Enough money for tuning to spend?
       require(msg.value>=options[_optionIndex].price);
       
       _changeAttributes(_tokenId,_optionIndex);
    }
    /// @dev Remove all Ether from the contract, which is the owner's cuts
    ///  as well as any Ether sent directly to the contract address.
    ///  Always transfers to the NFT contract, but can be called either by
    ///  the owner or the NFT contract.
    function withdrawBalance() external {
        address nftAddress = address(nonFungibleContract);

        require(
            msg.sender == owner ||
            msg.sender == nftAddress
        );
        // We are using this boolean method to make sure that even if one fails it will still work
        bool res = owner.send(this.balance);
    }

    function getOptionsForModel(uint64 _model) external view returns(uint256[] _optionsModel) {
        //uint256 tokenCount = balanceOf(_owner);

        //if (tokenCount == 0) {
            // Return an empty array
        //    return new uint256[](0);
        //} else {
            uint256[] memory result = new uint256[](modelIndexToOptionCount[_model]);
            //uint256 totalCars = totalSupply();
            uint256 resultIndex = 0;

            // We count on the fact that all cars have IDs starting at 0 and increasing
            // sequentially up to the optionCount count.
            uint256 optionId;

            for (optionId = 1; optionId <= optionCount; optionId++) {
                if (options[optionId].model == _model && options[optionId].active == true) {
                    result[resultIndex] = optionId;
                    resultIndex++;
                }
            }

            return result;
       // }
    }

}
/// @title ServiceStation for non-fungible tokens.
function ServiceStation(address _nftAddress) public {

    ERC721 candidateContract = ERC721(_nftAddress);
    //require(candidateContract.supportsInterface(InterfaceSignature_ERC721));
    nonFungibleContract = candidateContract;
    _newTuneOption(0,0,0,false,false,0,0);
        
}

/// @dev Constructor creates a reference to the NFT ownership contract
///  and verifies the owner cut is in the valid range.
/// @param _nftAddress - address of a deployed contract implementing
///  the Nonfungible Interface.