contract DragonCrowdsaleCore is Ownable, DragonPricing {
    
    using SafeMath for uint;
    
   // address public owner;
    address public beneficiary;
    address public charity;
    address public advisor;
    address public front;
    bool public advisorset;
    
    uint public tokensSold;
    uint public etherRaised;
    uint public presold;
    uint public presoldMax;
    
    uint public crowdsaleCounter;
    
   
    uint public advisorTotal;
    uint public advisorCut;
    
    Dragon public tokenReward;
    
   
    
    mapping ( address => bool ) public alreadyParticipated;
    
    
    
  
    
    modifier onlyFront() {
       require (msg.sender == front );
        _;
    }


    
    
    
    function DragonCrowdsaleCore(){
        
        tokenReward = Dragon( 0x814f67fa286f7572b041d041b1d99b432c9155ee ); // Dragon Token Address
        owner = msg.sender;
        beneficiary = msg.sender;
        charity = msg.sender;
        advisor = msg.sender;
       
        advisorset = false;
       
        presold = 0;
        presoldMax = 3500000000000000;
        crowdsaleCounter = 0;
        
        advisorCut = 0;
        advisorTotal = 1667 ether;
        
        
    }
    
   
    // runs during precrowdsale - can only be called by main crowdsale contract
    function precrowdsale ( address tokenholder ) onlyFront payable {
        
        
        require ( presold < presoldMax );
        uint award;  // amount of dragons to credit to tokenholder
        uint donation; // donation to charity
        require ( alreadyParticipated[ tokenholder ]  != true ) ;  
        alreadyParticipated[ tokenholder ] = true;
        
        DragonPricing pricingstructure = new DragonPricing();
        ( award, donation ) = pricingstructure.precrowdsalepricing( tokenholder , msg.value ); 
        
        tokenReward.transfer ( charity , donation ); // send dragons to charity
        presold = presold.add( award ); //add number of tokens sold in presale
        presold = presold.add( donation ); //add number of tokens sent via charity
        
        tokensSold = tokensSold.add(donation);  //add charity donation to total number of tokens sold 
        tokenReward.transfer ( tokenholder , award ); // immediate transfer of dragons to token buyer
        
        if ( advisorCut < advisorTotal ) { advisorSiphon();} 
       
        else 
          { beneficiary.transfer ( msg.value ); } //send ether to beneficiary
          
       
        etherRaised = etherRaised.add( msg.value ); // tallies ether raised
        tokensSold = tokensSold.add(award); // tallies total dragons sold
        
    }
    
    // runs when crowdsale is active - can only be called by main crowdsale contract
    function crowdsale ( address tokenholder  ) onlyFront payable {
        
        
        uint award;  // amount of dragons to send to tokenholder
        uint donation; // donation to charity
        DragonPricing pricingstructure = new DragonPricing();
        ( award , donation ) = pricingstructure.crowdsalepricing( tokenholder, msg.value, crowdsaleCounter ); 
         crowdsaleCounter += award;
        
        tokenReward.transfer ( tokenholder , award ); // immediate transfer to token holders
       
        if ( advisorCut < advisorTotal ) { advisorSiphon();} // send advisor his share
       
        else 
          { beneficiary.transfer ( msg.value ); } //send all ether to beneficiary
        
        etherRaised = etherRaised.add( msg.value );  //etherRaised += msg.value; // tallies ether raised
        tokensSold = tokensSold.add(award); //tokensSold  += award; // tallies total dragons sold
       
        
        
    }
    
    
    // pays the advisor part of the incoming ether
    function advisorSiphon() internal {
        
         uint share = msg.value/10;
         uint foradvisor = share;
             
           if ( (advisorCut + share) > advisorTotal ) foradvisor = advisorTotal.sub( advisorCut ); 
             
           advisor.transfer ( foradvisor );  // advisor gets 10% of the incoming ether
            
           advisorCut = advisorCut.add( foradvisor );
           beneficiary.transfer( share * 9 ); // the ether balance goes to the benfeciary
           if ( foradvisor != share ) beneficiary.transfer( share.sub(foradvisor) ); // if 10% of the incoming ether exceeds the total advisor is supposed to get , then this gives them a smaller share to not exceed max
        
        
        
    }
    
   

    
    // use this to set the crowdsale beneficiary address
    function transferBeneficiary ( address _newbeneficiary ) onlyOwner {
        
        require ( _newbeneficiary != 0x00 );
        beneficiary = _newbeneficiary;
        
    }
    
    // use this to set the charity address
    function transferCharity ( address _charity ) onlyOwner {
        
        require ( _charity != 0x00 );
        charity = _charity;
        
    }
    
    // sets crowdsale address
    function setFront ( address _front ) onlyOwner {
        
        require ( _front != 0x00 );
        front = _front;
        
    }
    // sets advisors address
    function setAdvisor ( address _advisor ) onlyOwner {
        
        require ( _advisor != 0x00 );
        require ( advisorset == false );
        advisorset = true;
        advisor = _advisor;
        
    }
    
   
        
    //empty the crowdsale contract of Dragons and forward balance to beneficiary
    function withdrawCrowdsaleDragons() onlyOwner{
        
        uint256 balance = tokenReward.balanceOf( address( this ) );
        tokenReward.transfer( beneficiary, balance );
        
        
    }
    
    //manually send different dragon packages
    function manualSend ( address tokenholder, uint packagenumber ) onlyOwner {
        
          require ( tokenholder != 0x00 );
          if ( packagenumber != 1 &&  packagenumber != 2 &&  packagenumber != 3 ) revert();
        
          uint award;
          uint donation;
          
          if ( packagenumber == 1 )  { award =   10800000000; donation =   800000000; }
          if ( packagenumber == 2 )  { award =  108800000000; donation =  8800000000; }
          if ( packagenumber == 3 )  { award = 1088800000000; donation = 88800000000; }
          
          
          tokenReward.transfer ( tokenholder , award ); 
          tokenReward.transfer ( charity , donation ); 
          
          presold = presold.add( award ); //add number of tokens sold in presale
          presold = presold.add( donation ); //add number of tokens sent via charity
          tokensSold = tokensSold.add(award); // tallies total dragons sold
          tokensSold = tokensSold.add(donation); // tallies total dragons sold
        
    }
   
   
    
    
    
}
function setFront ( address _front ) onlyOwner {
        
        require ( _front != 0x00 );
        front = _front;
        
    }
// sets crowdsale address