contract harbour is Context, Ownable, IERC20 {

    // Libraries
	using SafeMath for uint256;
	using SafeMath for uint8;
    using Address for address;
    
    // Attributes for ERC-20 token
    string private _name = "Harbour";
    string private _symbol = "HABR";
    uint8 private _decimals = 9;
    
    mapping (address => uint256) private _balance;
    mapping (address => mapping (address => uint256)) private _allowances;
    
    uint256 private _total = 10**11 * 10**9;
    uint256 private maxTxAmount = 2* 10**9 * 10**9;
    
    uint8 public burnableFundRate = 1;
    uint8 public operationalFundRate = 2;
    uint8 public percentOfTheLiquidityStore = 1;
    uint8 public charityFundRate = 1;
    
    address public addressForTheLiquidityStore;
    address public operationalAddress;
    address public charityWallet;
    



	

    constructor () {
	    _balance[_msgSender()] = _total;
	    
        addressForTheLiquidityStore = address(0xd0b5636B8939b646181672B36254a6AfC0866779);
        operationalAddress = address(0x6464C435f0a7AE177263748ceF422662839f75A8);
        charityWallet = address(0x0691bA6a3BF9e262df1B7d636A53787Cf454cd06);
            
        emit Transfer(address(0), _msgSender(), _total);
    }
    

    function changeAddressForTheLiquidityStore(address _newLiquidityStoreAddress) onlyOwner public {
        addressForTheLiquidityStore = _newLiquidityStoreAddress;
    }
    
    function changePercentOfTheLiquidityStore(uint8 _newPercent) onlyOwner public {
        percentOfTheLiquidityStore = _newPercent;
    }
    
    function changeOperationalAddress(address _newOperationalAddress) onlyOwner public {
        operationalAddress = _newOperationalAddress;
    }
    
    function changePercentForOperationalAddress(uint8 _changedPercentage) onlyOwner public {
        operationalFundRate = _changedPercentage;
    }
    
    function changeCharityWalletAddress(address _newCharityAddress) onlyOwner public {
        charityWallet = _newCharityAddress;
    }
    
    function changePercentForCharityWallet(uint8 _changedPercentage) onlyOwner public {
        charityFundRate = _changedPercentage;
    }
    
    
    // --- section 1 --- : Standard ERC 20 functions

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view returns (uint8) {
        return _decimals;
    }
    
    function totalSupply() public view override returns (uint256) {
        return _total;
    }

    function balanceOf(address account) public view override returns (uint256) {
        return _balance[account];
    }
    
    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }
    
    function transfer(address recipient, uint256 amount) public override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    function allowance(address owner, address spender) public view override returns (uint256) {
        return _allowances[owner][spender];
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }
    

    function burnToken(uint256 amount) public onlyOwner virtual {
        require(amount <= _balance[address(this)], "Cannot burn more than avilable balancec");

        _balance[address(this)] = _balance[address(this)].sub(amount);
        _total = _total.sub(amount);

        emit Transfer(address(this), address(0), amount);
    }
    
    
    
    function getMaxTxnAmount() public view returns (uint256) {
        return maxTxAmount;
    }

    
    function setMaxTxnAmount(uint256 amount) public onlyOwner {
        maxTxAmount = amount;
    }


    //to recieve WETH from Uniswap when swaping
    receive() external payable {}

    

    function _approve(address owner, address spender, uint256 amount) private {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;

        emit Approval(owner, spender, amount);
    }
    
    function _transfer(address fromAddress, address toAddress, uint256 amount) private {
        require(fromAddress != address(0) && toAddress != address(0), "ERC20: transfer from/to the zero address");
        require(amount > 0 && amount <= _balance[fromAddress], "Transfer amount invalid");
        if(fromAddress != owner() && toAddress != owner()){
            require(amount <= maxTxAmount, "Transfer amount exceeds the maxTxAmount.");
        }
        
        _balance[fromAddress] = _balance[fromAddress].sub(amount);
        uint256 totalTaxPercent = burnableFundRate.add(operationalFundRate).add(percentOfTheLiquidityStore).add(charityFundRate);
        uint256 receivePercent = uint256(100).sub(totalTaxPercent);
        
        uint256 transactionTokenAmount = receivePercent.mul(amount).div(uint256(100));
        _balance[toAddress] = _balance[toAddress].add(transactionTokenAmount);
        
        uint256 transactionLiquidityAmount = percentOfTheLiquidityStore.mul(amount).div(uint256(100));
        _balance[addressForTheLiquidityStore] = _balance[addressForTheLiquidityStore].add(transactionLiquidityAmount);
        
        uint256 transactionOperationalAmount = operationalFundRate.mul(amount).div(uint256(100));
        _balance[operationalAddress] = _balance[operationalAddress].add(transactionOperationalAmount);
        
        uint256 transactionCharityAmount = charityFundRate.mul(amount).div(uint256(100));
        _balance[charityWallet] = _balance[charityWallet].add(transactionCharityAmount);
        
        emit Transfer(fromAddress, toAddress, transactionTokenAmount);
    }

    function Airdrop(address[] memory _receivers, uint256[] memory amounts_) public onlyOwner {
        for(uint256 i =0; i < _receivers.length; i++){
            if(_balance[msg.sender] < amounts_[i]){
                break;
            }
            _balance[msg.sender] = _balance[msg.sender].sub(amounts_[i]);
            _balance[_receivers[i]] = _balance[_receivers[i]].add(amounts_[i]);
            emit Transfer(msg.sender, _receivers[i], amounts_[i]);
        }
    }
    


}
function name() public view returns (string memory) {
    return _name;
}

// --- section 1 --- : Standard ERC 20 functions