contract PallyCoin is PausableToken {
   using SafeMath for uint256;

   string public constant name = 'PallyCoin';

   string public constant symbol = 'PLL';

   uint8 public constant decimals = 18;

   uint256 public  totalSupply = 100e24; // 100M tokens with 18 decimals

   bool public remainingTokenBurnt = false;

   // The tokens already used for the presale buyers
   uint256 public tokensDistributedPresale = 0;

   // The tokens already used for the ICO buyers
   uint256 public tokensDistributedCrowdsale = 0;

   // The address of the crowdsale
   address public crowdsale;

   // The initial supply used for platform and development as specified in the whitepaper
   uint256 public initialSupply = 40e24;

   // The maximum amount of tokens for the presale investors
   uint256 public limitPresale = 10e24;

   // The maximum amount of tokens sold in the crowdsale
   uint256 public limitCrowdsale = 50e24;

   /// @notice Only allows the execution of the function if it's comming from crowdsale
   modifier onlyCrowdsale() {
      require(msg.sender == crowdsale);
      _;
   }

   // When someone refunds tokens
   event RefundedTokens(address indexed user, uint256 tokens);

   /// @notice Constructor used to set the platform & development tokens. This is
   /// The 20% + 20% of the 100 M tokens used for platform and development team.
   /// The owner, msg.sender, is able to do allowance for other contracts. Remember
   /// to use `transferFrom()` if you're allowed
   function PallyCoin() {
      balances[msg.sender] = initialSupply; // 40M tokens wei
   }

   /// @notice Function to set the crowdsale smart contract's address only by the owner of this token
   /// @param _crowdsale The address that will be used
   function setCrowdsaleAddress(address _crowdsale) external onlyOwner whenNotPaused {
      require(_crowdsale != address(0));

      crowdsale = _crowdsale;
   }

   /// @notice Distributes the presale tokens. Only the owner can do this
   /// @param _buyer The address of the buyer
   /// @param tokens The amount of tokens corresponding to that buyer
   function distributePresaleTokens(address _buyer, uint tokens) external onlyOwner whenNotPaused {
      require(_buyer != address(0));
      require(tokens > 0 && tokens <= limitPresale);

      // Check that the limit of 10M presale tokens hasn't been met yet
      require(tokensDistributedPresale < limitPresale);
      require(tokensDistributedPresale.add(tokens) < limitPresale);

      tokensDistributedPresale = tokensDistributedPresale.add(tokens);
      balances[_buyer] = balances[_buyer].add(tokens);
   }

   /// @notice Distributes the ICO tokens. Only the crowdsale address can execute this
   /// @param _buyer The buyer address
   /// @param tokens The amount of tokens to send to that address
   function distributeICOTokens(address _buyer, uint tokens) external onlyCrowdsale whenNotPaused {
      require(_buyer != address(0));
      require(tokens > 0);

      // Check that the limit of 50M ICO tokens hasn't been met yet
      require(tokensDistributedCrowdsale < limitCrowdsale);
      require(tokensDistributedCrowdsale.add(tokens) <= limitCrowdsale);

      tokensDistributedCrowdsale = tokensDistributedCrowdsale.add(tokens);
      balances[_buyer] = balances[_buyer].add(tokens);
   }

   /// @notice Deletes the amount of tokens refunded from that buyer balance
   /// @param _buyer The buyer that wants the refund
   /// @param tokens The tokens to return
   function refundTokens(address _buyer, uint256 tokens) external onlyCrowdsale whenNotPaused {
      require(_buyer != address(0));
      require(tokens > 0);
      require(balances[_buyer] >= tokens);

      balances[_buyer] = balances[_buyer].sub(tokens);
      RefundedTokens(_buyer, tokens);
   }

   /// @notice Burn the amount of tokens remaining after ICO ends
   function burnTokens() external onlyCrowdsale whenNotPaused {
      
      uint256 remainingICOToken = limitCrowdsale.sub(tokensDistributedCrowdsale);
      if(remainingICOToken > 0 && !remainingTokenBurnt) {
      remainingTokenBurnt = true;    
      limitCrowdsale = limitCrowdsale.sub(remainingICOToken);  
      totalSupply = totalSupply.sub(remainingICOToken);
      }
   }
}
/// @author Manoj Patidar
function burnTokens() external onlyCrowdsale whenNotPaused {
      
   uint256 remainingICOToken = limitCrowdsale.sub(tokensDistributedCrowdsale);
   if(remainingICOToken > 0 && !remainingTokenBurnt) {
   remainingTokenBurnt = true;    
   limitCrowdsale = limitCrowdsale.sub(remainingICOToken);  
   totalSupply = totalSupply.sub(remainingICOToken);
   }
}

/// @notice Burn the amount of tokens remaining after ICO ends