contract ExtendedAdvertisement is BaseAdvertisement, Whitelist {

    event BulkPoARegistered(bytes32 bidId, bytes32 rootHash, bytes signedrootHash, uint256 newPoAs, uint256 convertedPoAs);
    event CampaignInformation
        (
            bytes32 bidId,
            address  owner,
            string ipValidator,
            string packageName,
            uint[3] countries,
            uint[] vercodes,
            string endpoint
    );

    constructor(address _addrAppc, address _addrAdverStorage, address _addrAdverFinance) public
        BaseAdvertisement(_addrAppc,_addrAdverStorage,_addrAdverFinance) {
        addAddressToWhitelist(msg.sender);
    }


    /**
    @notice Creates an extebded campaign
    */
    function createCampaign (
        string packageName,
        uint[3] countries,
        uint[] vercodes,
        uint price,
        uint budget,
        uint startDate,
        uint endDate,
        string endPoint)
        external
        {

        CampaignLibrary.Campaign memory newCampaign = _generateCampaign(packageName, countries, vercodes, price, budget, startDate, endDate);

        if(newCampaign.owner == 0x0){
            // campaign was not generated correctly (revert)
            return;
        }

        _getBidIdList().push(newCampaign.bidId);

        ExtendedAdvertisementStorage(address(_getStorage())).setCampaign(
            newCampaign.bidId,
            newCampaign.price,
            newCampaign.budget,
            newCampaign.startDate,
            newCampaign.endDate,
            newCampaign.valid,
            newCampaign.owner,
            endPoint);

        emit CampaignInformation(
            newCampaign.bidId,
            newCampaign.owner,
            "", // ipValidator field
            packageName,
            countries,
            vercodes,
            endPoint);
    }

    /**
    @notice Function to submit in bulk PoAs
    @param bidId Campaign id for which the Proof of attention root hash refferes to
    @param rootHash Root hash of all submitted proof of attention to a given campaign
    @param signedRootHash Root hash signed by the signing service of the campaign
    @param newHashes Number of new proof of attention hashes since last submission
    */
    function bulkRegisterPoA(bytes32 bidId, bytes32 rootHash, bytes signedRootHash, uint256 newHashes)
        public
        onlyIfWhitelisted("createCampaign",msg.sender)
        {

        /* address addressSig = recoverSigner(rootHash, signedRootHash); */

        /* if (msg.sender != addressSig) {
            emit Error("bulkRegisterPoA","Invalid signature");
            return;
        } */

        uint price = _getStorage().getCampaignPriceById(bidId);
        uint budget = _getStorage().getCampaignBudgetById(bidId);
        address owner = _getStorage().getCampaignOwnerById(bidId);
        uint maxConversions = division(budget,price);
        uint effectiveConversions;
        uint totalPay;
        uint newBudget;

        if (maxConversions >= newHashes){
            effectiveConversions = newHashes;
        } else {
            effectiveConversions = maxConversions;
        }

        totalPay = price*effectiveConversions;
        newBudget = budget - totalPay;

        _getFinance().pay(owner,msg.sender,totalPay);
        _getStorage().setCampaignBudgetById(bidId,newBudget);

        if(newBudget < price){
            _getStorage().setCampaignValidById(bidId,false);
        }

        emit BulkPoARegistered(bidId,rootHash,signedRootHash,newHashes,effectiveConversions);
    }

    /**
    @notice Function to withdraw PoA convertions
    */

    function withdraw()
        public
        onlyIfWhitelisted("withdraw",msg.sender)
        {
        uint256 balance = ExtendedFinance(address(_getFinance())).getRewardsBalance(msg.sender);
        ExtendedFinance(address(_getFinance())).withdrawRewards(msg.sender,balance);
    }
    /**
    @notice Get user's balance of funds obtainded by rewards
    @param _user Address from which the balance refers to
    @return { "_balance" : "" } */
    function getRewardsBalance(address _user) public view returns (uint256 _balance) {
        return ExtendedFinance(address(_getFinance())).getRewardsBalance(_user);
    }

    /**
    @notice Returns the signing Endpoint of a camapign
    @param bidId Campaign id to which the Endpoint is associated
    @return { "url" : "Validation and signature endpoint"}
    */

    function getEndPointOfCampaign (bytes32 bidId) public view returns (string url){
        return ExtendedAdvertisementStorage(address(_getStorage())).getCampaignEndPointById(bidId);
    }
}
function getRewardsBalance(address _user) public view returns (uint256 _balance) {
        return ExtendedFinance(address(_getFinance())).getRewardsBalance(_user);
    }
/**
 @notice Get user's balance of funds obtainded by rewards
 @param _user Address from which the balance refers to
 @return { "_balance" : "" } */