contract    SocialLocker    is  DiamondTransaction
{
    uint256 public              minVotesCount         = 20;
    bool    public              isSocialLockerEnabled = true;

    mapping(address => bool)                        voteLockedWallets;
    mapping(address => uint256)                     refundTotalVotes;
    mapping(address => uint256)                     unlockingTotalVotes;
    mapping(address => bool)                        forbiddenVoters;
    mapping(address => mapping(address => bool))    votersMap;                  // Used to avoid one voter to vote twice on the same user

    event   OnLockedWallet(     address lockedWallet, uint256 timestamp);
    event   OnVotedForRefund(   address voter, address walletToVoteFor, uint256 voteScore, uint256 maxVotes);    // People has voted to refund all tokens from the involved wallet. it's a social voting
    event   OnVotedForUnlocking(address voter, address walletToVoteFor, uint256 voteScore, uint256 maxVotes);                            // People has voted to unlock this wallet
    event   OnVoterBannished(   address voter);
    event   OnVoterAllowed(     address voter);
    event   OnWalletBlocked(    address wallet);                            // The wallet will no more be allowed to send nor receive tokens
    event   OnSocialLockerWalletDepleted(address possibleFraudster);
    event   OnSocialLockerWalletUnlocked(address possibleFraudster);
    event   OnSocialLockerStateChanged(bool oldState, bool newState);
    event   OnSocialLockerChangeMinVoteCount(uint oldMinVoteCount, uint newMinVoteCount);
    event   OnWalletTaggedForSocialLocking(address taggedWallet);

    //--------------------------------------------------------------------------
    function    changeSocialLockerState(bool newState) public onlyAdmin  returns(uint256)
    {
        emit OnSocialLockerStateChanged(isSocialLockerEnabled, newState);

        isSocialLockerEnabled = newState;
        return 1;
    }
    //--------------------------------------------------------------------------
    function    changeMinVoteCount(uint256 newMinVoteCount) public onlyAdmin  returns(uint256)
    {
        emit OnSocialLockerChangeMinVoteCount(minVotesCount, newMinVoteCount);

        minVotesCount = newMinVoteCount;
        return 1;
    }
    //--------------------------------------------------------------------------
    function    tagWalletForVoting(address walletToTag) public onlyAdmin  returns(uint256)
    {
        voteLockedWallets[walletToTag]   = true;    // now people can vote for a refund or to unlock this wallet
        unlockingTotalVotes[walletToTag] = 0;       // no votes yet on this
        refundTotalVotes[walletToTag]    = 0;       // no vote yet

        emit OnWalletTaggedForSocialLocking(walletToTag);
        return 1;
    }
    //--------------------------------------------------------------------------
    function    voteForARefund(address voter, address possibleFraudster) public  returns(uint256)
    {
        uint256     currentVoteCount;
        uint256     sum;
        uint256     baseAmount;
        uint256     finalAmount;

        require(voteLockedWallets[possibleFraudster]  && 
                !forbiddenVoters[voter]               &&
                !votersMap[possibleFraudster][voter]  &&
                isSocialLockerEnabled);                     // Don't vote on wallets not yet locked by ADMIN. To avoid abuse and security issues 

        votersMap[possibleFraudster][voter] = true;           // Ok, this voter just voted, don't allow anymore votes from him on the possibleFraudster

        currentVoteCount = refundTotalVotes[possibleFraudster];
        sum              = currentVoteCount + 1;

        assert(currentVoteCount<sum);

        refundTotalVotes[possibleFraudster] = sum;

        emit OnVotedForRefund(voter, possibleFraudster, sum, minVotesCount);    // People has voted to refund all tokens from the involved wallet. it's a social voting

        //-----

        if (sum>=minVotesCount)         // The VOTE is Finished!!!
        {
            baseAmount   = balances[owner];
            finalAmount  = baseAmount + balances[possibleFraudster];

            assert(finalAmount >= baseAmount);

            balances[owner]           = finalAmount;        // The official Token owner receives back the token (voted as to be refunded)
            balances[possibleFraudster] = 0;                  // Sorry scammer, but the vote said  you won't have even 1 token in your wallet!

            voteLockedWallets[possibleFraudster] = false;   

            emit Transfer(possibleFraudster, owner, balances[possibleFraudster]);
        }
        return 1;
    }
    //--------------------------------------------------------------------------
    function    voteForUnlocking(address voter, address possibleFraudster) public  returns(uint256)
    {
        uint256     currentVoteCount;
        uint256     sum;

        require(voteLockedWallets[possibleFraudster]  && 
                !forbiddenVoters[voter]               &&
                !votersMap[possibleFraudster][voter]  &&
                isSocialLockerEnabled);                     // Don't vote on wallets not yet locked by ADMIN. To avoid abuse and security issues 

        votersMap[possibleFraudster][voter] = true;           // don't let the voter votes again for this possibleFraudster

        currentVoteCount = unlockingTotalVotes[possibleFraudster];
        sum              = currentVoteCount + 1;

        assert(currentVoteCount<sum);

        unlockingTotalVotes[possibleFraudster] = sum;

        emit OnVotedForUnlocking(voter, possibleFraudster, sum, minVotesCount);    // People has voted to refund all tokens from the involved wallet. it's a social voting

        //-----

        if (sum>=minVotesCount)         // The VOTE is Finished!!!
        {
            voteLockedWallets[possibleFraudster] = false;                         // Redemption allowed by the crowd
        }

        return 1;
    }
    //--------------------------------------------------------------------------
    function    banVoter(address voter) public onlyAdmin  returns(uint256)
    {
        forbiddenVoters[voter] = true;      // this user cannot vote anymore. A possible abuser

        emit OnVoterBannished(voter);
    }
    //--------------------------------------------------------------------------
    function    allowVoter(address voter) public onlyAdmin  returns(uint256)
    {
        forbiddenVoters[voter] = false;      // this user cannot vote anymore. A possible abuser

        emit OnVoterAllowed(voter);
    }
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------
    //--------------------------------------------------------------------------


}
////////////////////////////////////////////////////////////////////////////////
function    changeMinVoteCount(uint256 newMinVoteCount) public onlyAdmin  returns(uint256)
{
    emit OnSocialLockerChangeMinVoteCount(minVotesCount, newMinVoteCount);

    minVotesCount = newMinVoteCount;
    return 1;
}

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