contract    Token  is  SocialLocker
{
    address public                  validator;                              // Address of the guy who will validate any extend/reduce query. so it's considered as Admin2 here. Adm

    uint256 public                  minDelayBeforeStockChange = 6*3600;                          // StockReduce allowed EVERY 6 hours only

    uint256 public                  maxReduceInUnit      = 5000000;
        uint256 public                          maxReduce                        = maxReduceInUnit * 10**decimals;  // Don't allow a supply decrease if above this amount'

    uint256 public                  maxExtendInUnit      = maxReduceInUnit;
        uint256 public                          maxExtend                        = maxExtendInUnit * 10**decimals;  // Don't allow a supply decrease if above this amount'

    uint256        constant         decimalMultiplicator = 10**decimals;

    uint256                         lastReduceCallTime   = 0;

    bool    public                  isReduceStockValidated = false;         /// A validator (=2nd admin) needs to confitm the action before changing the stock quantity
    bool    public                  isExtendStockValidated = false;         /// same...

    uint256 public                  reduceVolumeInUnit   = 0;             /// Used when asking to reduce amount of token. validator needs to confirm first!
    uint256 public                  extendVolumeInUnit   = 0;             /// Used when asking to extend amount of token. validator needs to confirm first!

                //-----

    modifier onlyValidator()        { require(msg.sender==validator);   _; }

                //-----

    event   OnStockVolumeExtended(uint256 volumeInUnit, uint256 volumeInDecimal, uint256 newTotalSupply);
    event   OnStockVolumeReduced( uint256 volumeInUnit, uint256 volumeInDecimal, uint256 newTotalSupply);

    event   OnErrorLog(string functionName, string errorMsg);

    event   OnLogNumber(string section, uint256 value);

    event   OnMaxReduceChanged(uint256 maxReduceInUnit, uint256 oldQuantity);
    event   OnMaxExtendChanged(uint256 maxExtendInUnit, uint256 oldQuantity);

    event   OnValidationUserChanged(address oldValidator, address newValidator);

    //--------------------------------------------------------------------------
    constructor()   public 
    {
        validator = owner;
    }
    //--------------------------------------------------------------------------
    function    changeMaxReduceQuantity(uint256 newQuantityInUnit) public onlyAdmin   returns(uint256)
    {   
        uint256 oldQuantity = maxReduceInUnit;

        maxReduceInUnit = newQuantityInUnit;
        maxReduce       = maxReduceInUnit * 10**decimals;

        emit OnMaxReduceChanged(maxReduceInUnit, oldQuantity);

        return 1;        // used  for the API (outside the smartcontract)
    }
    //--------------------------------------------------------------------------
    function    changeMaxExtendQuantity(uint256 newQuantityInUnit) public onlyAdmin   returns(uint256)
    {
        uint256 oldQuantity = maxExtendInUnit;

        maxExtendInUnit = newQuantityInUnit;
        maxExtend       = maxExtendInUnit * 10**decimals;

        emit OnMaxExtendChanged(maxExtendInUnit, oldQuantity);

        return 1;        // used  for the API (outside the smartcontract)
    }
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    function    changeValidationUser(address newValidatorAddress) public onlyOwner returns(uint256)         // The validation user is the guy who will finally confirm a token reduce or a token extend
    {
        require(newValidatorAddress!=address(0x0));

        emit OnValidationUserChanged(validator, newValidatorAddress);

        validator = newValidatorAddress;

        return 1;
    }
    //--------------------------------------------------------------------------
    function    changeMinDelayBeforeStockChange(uint256 newDelayInSecond) public onlyAdmin returns(uint256)
    {
             if (newDelayInSecond<60)           return 0;   // not less than one minute
        else if (newDelayInSecond>24*3600)      return 0;   // not more than 24H of waiting

        minDelayBeforeStockChange = newDelayInSecond;

        emit OnLogNumber("changeMinDelayBeforeReduce", newDelayInSecond);

        return 1;           // for API use
    }
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    function    requestExtendStock(uint256 volumeInUnit) public onlyAdmin  returns(uint256)
    {
        require(volumeInUnit<=maxExtendInUnit);

        isExtendStockValidated = true;
        extendVolumeInUnit     = volumeInUnit;      // If a request was already done, the volume will be changed with this one

        return 1;                                   // for API use
    }
    //--------------------------------------------------------------------------
    function    cancelExtendStock() public onlyValidator returns(uint256)
    {
        isExtendStockValidated = false;             // Cancel any request posted by admin
        return 1;                                   // for API use
    }
    //--------------------------------------------------------------------------
    function    extendStock(uint256 volumeAllowedInUnit)   public onlyValidator   returns(uint256,uint256,uint256,uint256)
    {
        if (!isExtendStockValidated)                // Validator (admin2) must validate the query first!
        {
            emit OnErrorLog("extendStock", "Request not validated yet");
            return (0,0,0,0);
        }

        require(extendVolumeInUnit<=maxExtendInUnit);
        require(volumeAllowedInUnit==extendVolumeInUnit);       // Don't allow the admin set arbritrary volume before validation

        //-----

        uint256 extraVolumeInDecimal = extendVolumeInUnit * decimalMultiplicator;  // value in WEI

        //----- totalSupply      = totalSupply.add(extraVolumeInDecimal);

        uint256 baseAmount  = totalSupply;
        uint256 finalAmount = baseAmount + extraVolumeInDecimal;

        assert(finalAmount >= baseAmount);

        totalSupply = finalAmount;

        //----- balances[owner] = balances[owner].add(extraVolumeInDecimal);

        baseAmount  = balances[owner];
        finalAmount = baseAmount + extraVolumeInDecimal;

        assert(finalAmount >= baseAmount);

        balances[owner] = finalAmount;

        //-----

        isExtendStockValidated = false;                                 // reset for the next extend request

        emit OnStockVolumeExtended(extendVolumeInUnit, extraVolumeInDecimal, totalSupply);        

        return 
        (
            extendVolumeInUnit, 
            extraVolumeInDecimal, 
            balances[owner],
            totalSupply
        );                      // origin:0 OWNER    origin:1  AN_EXCHANGE
    }
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    function    requestReduceStock(uint256 volumeInUnit) public onlyAdmin  returns(uint256)
    {
        require(volumeInUnit<=maxReduceInUnit);

        isReduceStockValidated = true;
        reduceVolumeInUnit     = volumeInUnit;      // If a request was already done, the volume will be changed with this one

        return 1;                                   // for API use
    }
    //--------------------------------------------------------------------------
    function    cancelReduceStock() public onlyValidator returns(uint256)
    {
        isReduceStockValidated = false;             // Cancel any request posted by admin
        return 1;                                   // for API use
    }
    //--------------------------------------------------------------------------
    function    reduceStock(uint256 volumeAllowedInUnit) public onlyValidator   returns(uint256,uint256,uint256,uint256)
    {
        if (!isReduceStockValidated)                        // Validator (admin2) must validate the query first!
        {
            emit OnErrorLog("reduceStock", "Request not validated yet");
            return (0,0,0,0);
        }

        require(reduceVolumeInUnit<=maxReduceInUnit);
        require(volumeAllowedInUnit==reduceVolumeInUnit);       // Don't allow the admin set arbritrary volume before validation

        if (!isReduceAllowedNow())
        {
            return (0,0,0,0);
        }

        lastReduceCallTime = now;

        //-----

        uint256 reducedVolumeInDecimal = reduceVolumeInUnit * decimalMultiplicator;        // value in WEI

        //----- totalSupply     = totalSupply.sub(reducedVolumeInDecimal);

        uint256 baseAmount  = totalSupply;
        uint256 finalAmount = baseAmount - reducedVolumeInDecimal;

        assert(finalAmount <= baseAmount);

        totalSupply = finalAmount;

        //----- balances[owner] = balances[owner].sub(reducedVolumeInDecimal);

        baseAmount  = balances[owner];
        finalAmount = baseAmount - reducedVolumeInDecimal;

        assert(finalAmount <= baseAmount);

        balances[owner] = finalAmount;

        //-----

        emit OnStockVolumeReduced(reduceVolumeInUnit, reducedVolumeInDecimal, totalSupply);        

        return
        (    
            reduceVolumeInUnit, 
            reducedVolumeInDecimal, 
            balances[owner],
            totalSupply
        );
    }
    //--------------------------------------------------------------------------
    function    isReduceAllowedNow() public view  returns(bool)
    {
        uint256 delay = now - lastReduceCallTime;

        return (delay >= minDelayBeforeStockChange);
    }
    //--------------------------------------------------------------------------
    function    getStockBalance() public view returns(uint256)
    {
        return totalSupply;
    }
}
////////////////////////////////////////////////////////////////////////////////
function    changeMinDelayBeforeStockChange(uint256 newDelayInSecond) public onlyAdmin returns(uint256)
{
         if (newDelayInSecond<60)           return 0;   // not less than one minute
    else if (newDelayInSecond>24*3600)      return 0;   // not more than 24H of waiting

    minDelayBeforeStockChange = newDelayInSecond;

    emit OnLogNumber("changeMinDelayBeforeReduce", newDelayInSecond);

    return 1;           // for API use
}

//--------------------------------------------------------------------------