contract GIZAToken is ERC20, Ownable {

    using SafeMath for uint256;
    //The name of the  token
    bytes32 public name;
    //The token symbol
    bytes32 public symbol;
    //The precision used in the calculations in contract
    uint8 public decimals;   
    //To denote the locking on transfer of tokens among token holders
    bool public locked;
	// Founder address. Need to froze for 8 moths
	address public founder;
	// Team address. Need to froze for 8 moths
	address public team;
	// Start of Pre-ICO date
	uint256 public start;
	
    //Mapping to relate number of  token to the account
    mapping(address => uint256 ) balances;
    //Mapping to relate owner and spender to the tokens allowed to transfer from owner
    mapping(address => mapping(address => uint256)) allowed;

    event Burn(address indexed burner, uint indexed value);  

    /**
    * @dev Constructor of GIZA
    */
    function GIZAToken(address _founder, address _team) public {
		require( _founder != address(0) && _team != address(0) );
        /* Public variables of the token */
        //The name of the  token
        name = "GIZA Token";
        //The token symbol
        symbol = "GIZA";
        //Number of zeroes to be treated as decimals
        decimals = 18;       
        //initial token supply 0
        totalSupply = 368e23; // 36 800 000 tokens total
        //Transfer of tokens is locked (not allowed) when contract is deployed
        locked = true;
		// Save founder and team address
		founder = _founder;
		team = _team;
		balances[msg.sender] = totalSupply;
		start = 0;
    }
      
	function startNow() external onlyOwner {
		start = now;
	}
	  
    //To handle ERC20 short address attack
    modifier onlyPayloadSize(uint256 size) {
       require(msg.data.length >= size + 4);
       _;
    }

    modifier onlyUnlocked() { 
      require (!locked); 
      _; 
    }
	
    modifier ifNotFroze() { 
		if ( 
		  (msg.sender == founder || msg.sender == team) && 
		  (start == 0 || now < (start + 80 days) ) ) revert();
		_;
    }
    
    //To enable transfer of tokens
    function unlockTransfer() external onlyOwner{
      locked = false;
    }

    /**
    * @dev Check balance of given account address
    *
    * @param _owner The address account whose balance you want to know
    * @return balance of the account
    */
    function balanceOf(address _owner) public view returns (uint256 _value){
        return balances[_owner];
    }

    /**
    * @dev Transfer tokens to an address given by sender
    *
    * @param _to The address which you want to transfer to
    * @param _value the amount of tokens to be transferred
    * @return A bool if the transfer was a success or not
    */
    function transfer(address _to, uint256 _value) onlyPayloadSize(2 * 32) onlyUnlocked ifNotFroze public returns(bool _success) {
        require( _to != address(0) );
        if((balances[msg.sender] > _value) && _value > 0){
			balances[msg.sender] = balances[msg.sender].Sub(_value);
			balances[_to] = balances[_to].Add(_value);
			Transfer(msg.sender, _to, _value);
			return true;
        }
        else{
            return false;
        }
    }

    /**
    * @dev Transfer tokens from one address to another, for ERC20.
    *
    * @param _from The address which you want to send tokens from
    * @param _to The address which you want to transfer to
    * @param _value the amount of tokens to be transferred
    * @return A bool if the transfer was a success or not
    */
    function transferFrom(address _from, address _to, uint256 _value) onlyPayloadSize(3 * 32) onlyUnlocked ifNotFroze public returns (bool success){
        require( _to != address(0) && (_from != address(0)));
        if((_value > 0)
           && (allowed[_from][msg.sender] > _value )){
            balances[_from] = balances[_from].Sub(_value);
            balances[_to] = balances[_to].Add(_value);
            allowed[_from][msg.sender] = allowed[_from][msg.sender].Sub(_value);
            Transfer(_from, _to, _value);
            return true;
        }
        else{
            return false;
        }
    }

    /**
    * @dev Function to check the amount of tokens that an owner has allowed a spender to recieve from owner.
    *
    * @param _owner address The address which owns the funds.
    * @param _spender address The address which will spend the funds.
    * @return A uint256 specifying the amount of tokens still available for the spender to spend.
    */
    function allowance(address _owner, address _spender) public view returns (uint256){
        return allowed[_owner][_spender];
    }

    /**
    * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
    *
    * @param _spender The address which will spend the funds.
    * @param _value The amount of tokens to be spent.
    */
    function approve(address _spender, uint256 _value) public returns (bool){
        if( (_value > 0) && (_spender != address(0)) && (balances[msg.sender] >= _value)){
            allowed[msg.sender][_spender] = _value;
            Approval(msg.sender, _spender, _value);
            return true;
        }
        else{
            return false;
        }
    }
    
    // Only owner can burn own tokens
    function burn(uint _value) public onlyOwner {
        require(_value > 0);
        address burner = msg.sender;
        balances[burner] = balances[burner].Sub(_value);
        totalSupply = totalSupply.Sub(_value);
        Burn(burner, _value);
    }

}
/**
 * @title GIZA to implement token
 */
function unlockTransfer() external onlyOwner{
  locked = false;
}

//To enable transfer of tokens