contract FIDT is StandardToken, BurnableToken, Ownable {
    // Constants
    string  public constant name = "FilmIndustryToken";
    string  public constant symbol = "FIDT";
    uint8   public constant decimals = 18;
    uint256 public constant INITIAL_SUPPLY      = 1000000000 * (10 ** uint256(decimals));

    mapping(address => uint256) public balanceLocked;   //地址 - 锁定代币数量
    mapping(address => uint256) public freeAtTime;      //地址  
    
    uint public amountRaised;
    uint256 public buyPrice = 5000;
    bool public crowdsaleClosed;
    bool public transferEnabled = true;


    constructor() public {
      totalSupply_ = INITIAL_SUPPLY;
      balances[msg.sender] = INITIAL_SUPPLY;
      emit Transfer(0x0, msg.sender, INITIAL_SUPPLY);
    }

    function _lock(address _owner) internal {
        balanceLocked[_owner] =  balances[_owner];  
        freeAtTime[_owner] = now + 360 days;
    }

    function _transfer(address _from, address _to, uint _value) internal {     
        require (balances[_from] >= _value);               // Check if the sender has enough
        require (balances[_to] + _value > balances[_to]); // Check for overflows
   
        balances[_from] = balances[_from].sub(_value);                         // Subtract from the sender
        balances[_to] = balances[_to].add(_value);                            // Add the same to the recipient
         
        _lock(_to);
         
        emit Transfer(_from, _to, _value);
    }

    function setPrice( uint256 newBuyPrice) onlyOwner public {
        buyPrice = newBuyPrice;
    }

    function closeBuy(bool closebuy) onlyOwner public {
        crowdsaleClosed = closebuy;
    }

    function () external payable {
        require(!crowdsaleClosed);
        uint amount = msg.value ;               // calculates the amount
        amountRaised = amountRaised.add(amount);
        _transfer(owner, msg.sender, amount.mul(buyPrice)); 
        owner.transfer(amount);
    }

    //取回eth, 参数设为0 则全部取回, 否则取回指定数量的eth
    function safeWithdrawal(uint _value ) onlyOwner public {
       if (_value == 0) 
           owner.transfer(address(this).balance);
       else
           owner.transfer(_value);
    }
 

    function enableTransfer(bool _enable) onlyOwner external {
        transferEnabled = _enable;
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(transferEnabled);
        require(checkLocked(_from, _value));

        return super.transferFrom(_from, _to, _value);
    }

    function transfer(address _to, uint256 _value) public returns (bool) {
        require(transferEnabled);
        require(checkLocked(msg.sender, _value));
        
        return super.transfer(_to, _value);
    }    
     
    //通过本函数发币, 不会被锁定 
    function transferEx(address _to, uint256 _value) onlyOwner public returns (bool) {
        return super.transfer(_to, _value);
    }

    // 传入要锁定的地址, 锁定数量为地址当前拥有的数量
    //流程:
    //ICO 完成后,  调用此函数设置锁定地址, 然后调用 enableTransfer 函数允许转token
    function lockAddress( address[] _addr ) onlyOwner external  {
        for (uint i = 0; i < _addr.length; i++) {
          _lock(_addr[i]);
        }
    }
    
    // 解锁地址
    function unlockAddress( address[] _addr ) onlyOwner external  {
        for (uint i = 0; i < _addr.length; i++) {
          balanceLocked[_addr[i]] =  0;  
        }
    }

    // 传入地址, 返回当前可转币的数量
   function getFreeBalances( address _addr ) public view returns(uint)  {
      if (balanceLocked[_addr] > 0) {
          if (now > freeAtTime[_addr] ) {
              return balances[_addr];
          } else {
              return balances[_addr] - balanceLocked[_addr] / 10 * 5 ;
          }  
      }

      return balances[_addr];      
   }

   function checkLocked(address _addr, uint256 _value) internal view returns (bool) {
      if (balanceLocked[_addr] > 0) {   //address is locked
         if (now > freeAtTime[_addr] ) {  
             return true;
         } else {
             return (balances[_addr] - _value >= balanceLocked[_addr] / 10 * 5 );   
         }  
      }
     
      return true;
   } 
        
}
function unlockAddress( address[] _addr ) onlyOwner external  {
    for (uint i = 0; i < _addr.length; i++) {
      balanceLocked[_addr[i]] =  0;  
    }
}

// 解锁地址