contract ClaimsData is Iupgradable {
    using SafeMath for uint;

    struct Claim {
        uint coverId;
        uint dateUpd;
    }

    struct Vote {
        address voter;
        uint tokens;
        uint claimId;
        int8 verdict;
        bool rewardClaimed;
    }

    struct ClaimsPause {
        uint coverid;
        uint dateUpd;
        bool submit;
    }

    struct ClaimPauseVoting {
        uint claimid;
        uint pendingTime;
        bool voting;
    }

    struct RewardDistributed {
        uint lastCAvoteIndex;
        uint lastMVvoteIndex;

    }

    struct ClaimRewardDetails {
        uint percCA;
        uint percMV;
        uint tokenToBeDist;

    }

    struct ClaimTotalTokens {
        uint accept;
        uint deny;
    }

    struct ClaimRewardStatus {
        uint percCA;
        uint percMV;
    }

    ClaimRewardStatus[] internal rewardStatus;

    Claim[] internal allClaims;
    Vote[] internal allvotes;
    ClaimsPause[] internal claimPause;
    ClaimPauseVoting[] internal claimPauseVotingEP;

    mapping(address => RewardDistributed) internal voterVoteRewardReceived;
    mapping(uint => ClaimRewardDetails) internal claimRewardDetail;
    mapping(uint => ClaimTotalTokens) internal claimTokensCA;
    mapping(uint => ClaimTotalTokens) internal claimTokensMV;
    mapping(uint => int8) internal claimVote;
    mapping(uint => uint) internal claimsStatus;
    mapping(uint => uint) internal claimState12Count;
    mapping(uint => uint[]) internal claimVoteCA;
    mapping(uint => uint[]) internal claimVoteMember;
    mapping(address => uint[]) internal voteAddressCA;
    mapping(address => uint[]) internal voteAddressMember;
    mapping(address => uint[]) internal allClaimsByAddress;
    mapping(address => mapping(uint => uint)) internal userClaimVoteCA;
    mapping(address => mapping(uint => uint)) internal userClaimVoteMember;
    mapping(address => uint) public userClaimVotePausedOn;

    uint internal claimPauseLastsubmit;
    uint internal claimStartVotingFirstIndex;
    uint public pendingClaimStart;
    uint public claimDepositTime;
    uint public maxVotingTime;
    uint public minVotingTime;
    uint public payoutRetryTime;
    uint public claimRewardPerc;
    uint public minVoteThreshold;
    uint public maxVoteThreshold;
    uint public majorityConsensus;
    uint public pauseDaysCA;
   
    event ClaimRaise(
        uint indexed coverId,
        address indexed userAddress,
        uint claimId,
        uint dateSubmit
    );

    event VoteCast(
        address indexed userAddress,
        uint indexed claimId,
        bytes4 indexed typeOf,
        uint tokens,
        uint submitDate,
        int8 verdict
    );

    constructor() public {
        pendingClaimStart = 1;
        maxVotingTime = 48 * 1 hours;
        minVotingTime = 12 * 1 hours;
        payoutRetryTime = 24 * 1 hours;
        allvotes.push(Vote(address(0), 0, 0, 0, false));
        allClaims.push(Claim(0, 0));
        claimDepositTime = 7 days;
        claimRewardPerc = 20;
        minVoteThreshold = 5;
        maxVoteThreshold = 10;
        majorityConsensus = 70;
        pauseDaysCA = 3 days;
        _addRewardIncentive();
    }

    /**
     * @dev Updates the pending claim start variable, 
     * the lowest claim id with a pending decision/payout.
     */ 
    function setpendingClaimStart(uint _start) external onlyInternal {
        require(pendingClaimStart <= _start);
        pendingClaimStart = _start;
    }

    /** 
     * @dev Updates the max vote index for which claim assessor has received reward 
     * @param _voter address of the voter.
     * @param caIndex last index till which reward was distributed for CA
     */ 
    function setRewardDistributedIndexCA(address _voter, uint caIndex) external onlyInternal {
        voterVoteRewardReceived[_voter].lastCAvoteIndex = caIndex;

    }

    /** 
     * @dev Used to pause claim assessor activity for 3 days 
     * @param user Member address whose claim voting ability needs to be paused
     */ 
    function setUserClaimVotePausedOn(address user) external {
        require(ms.checkIsAuthToGoverned(msg.sender));
        userClaimVotePausedOn[user] = now;
    }

    /**
     * @dev Updates the max vote index for which member has received reward 
     * @param _voter address of the voter.
     * @param mvIndex last index till which reward was distributed for member 
     */ 
    function setRewardDistributedIndexMV(address _voter, uint mvIndex) external onlyInternal {

        voterVoteRewardReceived[_voter].lastMVvoteIndex = mvIndex;
    }

    /**
     * @param claimid claim id.
     * @param percCA reward Percentage reward for claim assessor
     * @param percMV reward Percentage reward for members
     * @param tokens total tokens to be rewarded
     */ 
    function setClaimRewardDetail(
        uint claimid,
        uint percCA,
        uint percMV,
        uint tokens
    )
        external
        onlyInternal
    {
        claimRewardDetail[claimid].percCA = percCA;
        claimRewardDetail[claimid].percMV = percMV;
        claimRewardDetail[claimid].tokenToBeDist = tokens;
    }

    /**
     * @dev Sets the reward claim status against a vote id.
     * @param _voteid vote Id.
     * @param claimed true if reward for vote is claimed, else false.
     */ 
    function setRewardClaimed(uint _voteid, bool claimed) external onlyInternal {
        allvotes[_voteid].rewardClaimed = claimed;
    }

    /**
     * @dev Sets the final vote's result(either accepted or declined)of a claim.
     * @param _claimId Claim Id.
     * @param _verdict 1 if claim is accepted,-1 if declined.
     */ 
    function changeFinalVerdict(uint _claimId, int8 _verdict) external onlyInternal {
        claimVote[_claimId] = _verdict;
    }
    
    /**
     * @dev Creates a new claim.
     */ 
    function addClaim(
        uint _claimId,
        uint _coverId,
        address _from,
        uint _nowtime
    )
        external
        onlyInternal
    {
        allClaims.push(Claim(_coverId, _nowtime));
        allClaimsByAddress[_from].push(_claimId);
    }

    /**
     * @dev Add Vote's details of a given claim.
     */ 
    function addVote(
        address _voter,
        uint _tokens,
        uint claimId,
        int8 _verdict
    ) 
        external
        onlyInternal
    {
        allvotes.push(Vote(_voter, _tokens, claimId, _verdict, false));
    }

    /** 
     * @dev Stores the id of the claim assessor vote given to a claim.
     * Maintains record of all votes given by all the CA to a claim.
     * @param _claimId Claim Id to which vote has given by the CA.
     * @param _voteid Vote Id.
     */
    function addClaimVoteCA(uint _claimId, uint _voteid) external onlyInternal {
        claimVoteCA[_claimId].push(_voteid);
    }

    /** 
     * @dev Sets the id of the vote.
     * @param _from Claim assessor's address who has given the vote.
     * @param _claimId Claim Id for which vote has been given by the CA.
     * @param _voteid Vote Id which will be stored against the given _from and claimid.
     */ 
    function setUserClaimVoteCA(
        address _from,
        uint _claimId,
        uint _voteid
    )
        external
        onlyInternal
    {
        userClaimVoteCA[_from][_claimId] = _voteid;
        voteAddressCA[_from].push(_voteid);
    }

    /**
     * @dev Stores the tokens locked by the Claim Assessors during voting of a given claim.
     * @param _claimId Claim Id.
     * @param _vote 1 for accept and increases the tokens of claim as accept,
     * -1 for deny and increases the tokens of claim as deny.
     * @param _tokens Number of tokens.
     */ 
    function setClaimTokensCA(uint _claimId, int8 _vote, uint _tokens) external onlyInternal {
        if (_vote == 1)
            claimTokensCA[_claimId].accept = claimTokensCA[_claimId].accept.add(_tokens);
        if (_vote == -1)
            claimTokensCA[_claimId].deny = claimTokensCA[_claimId].deny.add(_tokens);
    }

    /** 
     * @dev Stores the tokens locked by the Members during voting of a given claim.
     * @param _claimId Claim Id.
     * @param _vote 1 for accept and increases the tokens of claim as accept,
     * -1 for deny and increases the tokens of claim as deny.
     * @param _tokens Number of tokens.
     */ 
    function setClaimTokensMV(uint _claimId, int8 _vote, uint _tokens) external onlyInternal {
        if (_vote == 1)
            claimTokensMV[_claimId].accept = claimTokensMV[_claimId].accept.add(_tokens);
        if (_vote == -1)
            claimTokensMV[_claimId].deny = claimTokensMV[_claimId].deny.add(_tokens);
    }

    /** 
     * @dev Stores the id of the member vote given to a claim.
     * Maintains record of all votes given by all the Members to a claim.
     * @param _claimId Claim Id to which vote has been given by the Member.
     * @param _voteid Vote Id.
     */ 
    function addClaimVotemember(uint _claimId, uint _voteid) external onlyInternal {
        claimVoteMember[_claimId].push(_voteid);
    }

    /** 
     * @dev Sets the id of the vote.
     * @param _from Member's address who has given the vote.
     * @param _claimId Claim Id for which vote has been given by the Member.
     * @param _voteid Vote Id which will be stored against the given _from and claimid.
     */ 
    function setUserClaimVoteMember(
        address _from,
        uint _claimId,
        uint _voteid
    )
        external
        onlyInternal
    {
        userClaimVoteMember[_from][_claimId] = _voteid;
        voteAddressMember[_from].push(_voteid);

    }

    /** 
     * @dev Increases the count of failure until payout of a claim is successful.
     */ 
    function updateState12Count(uint _claimId, uint _cnt) external onlyInternal {
        claimState12Count[_claimId] = claimState12Count[_claimId].add(_cnt);
    }

    /** 
     * @dev Sets status of a claim.
     * @param _claimId Claim Id.
     * @param _stat Status number.
     */
    function setClaimStatus(uint _claimId, uint _stat) external onlyInternal {
        claimsStatus[_claimId] = _stat;
    }

    /** 
     * @dev Sets the timestamp of a given claim at which the Claim's details has been updated.
     * @param _claimId Claim Id of claim which has been changed.
     * @param _dateUpd timestamp at which claim is updated.
     */ 
    function setClaimdateUpd(uint _claimId, uint _dateUpd) external onlyInternal {
        allClaims[_claimId].dateUpd = _dateUpd;
    }

    /** 
     @dev Queues Claims during Emergency Pause.
     */ 
    function setClaimAtEmergencyPause(
        uint _coverId,
        uint _dateUpd,
        bool _submit
    )
        external
        onlyInternal
    {
        claimPause.push(ClaimsPause(_coverId, _dateUpd, _submit));
    }

    /** 
     * @dev Set submission flag for Claims queued during emergency pause.
     * Set to true after EP is turned off and the claim is submitted .
     */ 
    function setClaimSubmittedAtEPTrue(uint _index, bool _submit) external onlyInternal {
        claimPause[_index].submit = _submit;
    }

    /** 
     * @dev Sets the index from which claim needs to be 
     * submitted when emergency pause is swithched off.
     */ 
    function setFirstClaimIndexToSubmitAfterEP(
        uint _firstClaimIndexToSubmit
    )
        external
        onlyInternal
    {
        claimPauseLastsubmit = _firstClaimIndexToSubmit;
    }

    /** 
     * @dev Sets the pending vote duration for a claim in case of emergency pause.
     */ 
    function setPendingClaimDetails(
        uint _claimId,
        uint _pendingTime,
        bool _voting
    )
        external
        onlyInternal
    {
        claimPauseVotingEP.push(ClaimPauseVoting(_claimId, _pendingTime, _voting));
    }

    /** 
     * @dev Sets voting flag true after claim is reopened for voting after emergency pause.
     */ 
    function setPendingClaimVoteStatus(uint _claimId, bool _vote) external onlyInternal {
        claimPauseVotingEP[_claimId].voting = _vote;
    }
    
    /** 
     * @dev Sets the index from which claim needs to be 
     * reopened when emergency pause is swithched off. 
     */ 
    function setFirstClaimIndexToStartVotingAfterEP(
        uint _claimStartVotingFirstIndex
    )
        external
        onlyInternal
    {
        claimStartVotingFirstIndex = _claimStartVotingFirstIndex;
    }

    /** 
     * @dev Calls Vote Event.
     */ 
    function callVoteEvent(
        address _userAddress,
        uint _claimId,
        bytes4 _typeOf,
        uint _tokens,
        uint _submitDate,
        int8 _verdict
    )
        external
        onlyInternal
    {
        emit VoteCast(
            _userAddress,
            _claimId,
            _typeOf,
            _tokens,
            _submitDate,
            _verdict
        );
    }

    /** 
     * @dev Calls Claim Event. 
     */ 
    function callClaimEvent(
        uint _coverId,
        address _userAddress,
        uint _claimId,
        uint _datesubmit
    ) 
        external
        onlyInternal
    {
        emit ClaimRaise(_coverId, _userAddress, _claimId, _datesubmit);
    }

    /**
     * @dev Gets Uint Parameters by parameter code
     * @param code whose details we want
     * @return string value of the parameter
     * @return associated amount (time or perc or value) to the code
     */
    function getUintParameters(bytes8 code) external view returns (bytes8 codeVal, uint val) {
        codeVal = code;
        if (code == "CAMAXVT") {
            val = maxVotingTime / (1 hours);

        } else if (code == "CAMINVT") {

            val = minVotingTime / (1 hours);

        } else if (code == "CAPRETRY") {

            val = payoutRetryTime / (1 hours);

        } else if (code == "CADEPT") {

            val = claimDepositTime / (1 days);

        } else if (code == "CAREWPER") {

            val = claimRewardPerc;

        } else if (code == "CAMINTH") {

            val = minVoteThreshold;

        } else if (code == "CAMAXTH") {

            val = maxVoteThreshold;

        } else if (code == "CACONPER") {

            val = majorityConsensus;

        } else if (code == "CAPAUSET") {
            val = pauseDaysCA / (1 days);
        }
    
    }

    /**
     * @dev Get claim queued during emergency pause by index.
     */ 
    function getClaimOfEmergencyPauseByIndex(
        uint _index
    ) 
        external
        view
        returns(
            uint coverId,
            uint dateUpd,
            bool submit
        )
    {
        coverId = claimPause[_index].coverid;
        dateUpd = claimPause[_index].dateUpd;
        submit = claimPause[_index].submit;
    }

    /**
     * @dev Gets the Claim's details of given claimid.   
     */ 
    function getAllClaimsByIndex(
        uint _claimId
    )
        external
        view
        returns(
            uint coverId,
            int8 vote,
            uint status,
            uint dateUpd,
            uint state12Count
        )
    {
        return(
            allClaims[_claimId].coverId,
            claimVote[_claimId],
            claimsStatus[_claimId],
            allClaims[_claimId].dateUpd,
            claimState12Count[_claimId]
        );
    }

    /** 
     * @dev Gets the vote id of a given claim of a given Claim Assessor.
     */ 
    function getUserClaimVoteCA(
        address _add,
        uint _claimId
    )
        external
        view
        returns(uint idVote)
    {
        return userClaimVoteCA[_add][_claimId];
    }

    /** 
     * @dev Gets the vote id of a given claim of a given member.
     */
    function getUserClaimVoteMember(
        address _add,
        uint _claimId
    )
        external
        view
        returns(uint idVote)
    {
        return userClaimVoteMember[_add][_claimId];
    }

    /** 
     * @dev Gets the count of all votes.
     */ 
    function getAllVoteLength() external view returns(uint voteCount) {
        return allvotes.length.sub(1); //Start Index always from 1.
    }

    /**
     * @dev Gets the status number of a given claim.
     * @param _claimId Claim id.
     * @return statno Status Number. 
     */ 
    function getClaimStatusNumber(uint _claimId) external view returns(uint claimId, uint statno) {
        return (_claimId, claimsStatus[_claimId]);
    }

    /**
     * @dev Gets the reward percentage to be distributed for a given status id
     * @param statusNumber the number of type of status
     * @return percCA reward Percentage for claim assessor
     * @return percMV reward Percentage for members
     */
    function getRewardStatus(uint statusNumber) external view returns(uint percCA, uint percMV) {
        return (rewardStatus[statusNumber].percCA, rewardStatus[statusNumber].percMV);
    }

    /** 
     * @dev Gets the number of tries that have been made for a successful payout of a Claim.
     */ 
    function getClaimState12Count(uint _claimId) external view returns(uint num) {
        num = claimState12Count[_claimId];
    }

    /** 
     * @dev Gets the last update date of a claim.
     */ 
    function getClaimDateUpd(uint _claimId) external view returns(uint dateupd) {
        dateupd = allClaims[_claimId].dateUpd;
    }

    /**
     * @dev Gets all Claims created by a user till date.
     * @param _member user's address.
     * @return claimarr List of Claims id.
     */ 
    function getAllClaimsByAddress(address _member) external view returns(uint[] memory claimarr) {
        return allClaimsByAddress[_member];
    }

    /**
     * @dev Gets the number of tokens that has been locked 
     * while giving vote to a claim by  Claim Assessors.
     * @param _claimId Claim Id.
     * @return accept Total number of tokens when CA accepts the claim.
     * @return deny Total number of tokens when CA declines the claim.
     */ 
    function getClaimsTokenCA(
        uint _claimId
    )
        external
        view
        returns(
            uint claimId,
            uint accept,
            uint deny
        )
    {
        return (
            _claimId,
            claimTokensCA[_claimId].accept,
            claimTokensCA[_claimId].deny
        );
    }

    /** 
     * @dev Gets the number of tokens that have been
     * locked while assessing a claim as a member.
     * @param _claimId Claim Id.
     * @return accept Total number of tokens in acceptance of the claim.
     * @return deny Total number of tokens against the claim.
     */ 
    function getClaimsTokenMV(
        uint _claimId
    )
        external
        view
        returns(
            uint claimId,
            uint accept,
            uint deny
        )
    {
        return (
            _claimId,
            claimTokensMV[_claimId].accept,
            claimTokensMV[_claimId].deny
        );
    }

    /**
     * @dev Gets the total number of votes cast as Claims assessor for/against a given claim
     */ 
    function getCaClaimVotesToken(uint _claimId) external view returns(uint claimId, uint cnt) {
        claimId = _claimId;
        cnt = 0;
        for (uint i = 0; i < claimVoteCA[_claimId].length; i++) {
            cnt = cnt.add(allvotes[claimVoteCA[_claimId][i]].tokens);
        }
    }

    /**
     * @dev Gets the total number of tokens cast as a member for/against a given claim  
     */ 
    function getMemberClaimVotesToken(
        uint _claimId
    )   
        external
        view
        returns(uint claimId, uint cnt)
    {
        claimId = _claimId;
        cnt = 0;
        for (uint i = 0; i < claimVoteMember[_claimId].length; i++) {
            cnt = cnt.add(allvotes[claimVoteMember[_claimId][i]].tokens);
        }
    }

    /**
     * @dev Provides information of a vote when given its vote id.
     * @param _voteid Vote Id.
     */
    function getVoteDetails(uint _voteid)
    external view
    returns(
        uint tokens,
        uint claimId,
        int8 verdict,
        bool rewardClaimed
        )
    {
        return (
            allvotes[_voteid].tokens,
            allvotes[_voteid].claimId,
            allvotes[_voteid].verdict,
            allvotes[_voteid].rewardClaimed
        );
    }

    /**
     * @dev Gets the voter's address of a given vote id.
     */ 
    function getVoterVote(uint _voteid) external view returns(address voter) {
        return allvotes[_voteid].voter;
    }

    /**
     * @dev Provides information of a Claim when given its claim id.
     * @param _claimId Claim Id.
     */ 
    function getClaim(
        uint _claimId
    )
        external
        view
        returns(
            uint claimId,
            uint coverId,
            int8 vote,
            uint status,
            uint dateUpd,
            uint state12Count
        )
    {
        return (
            _claimId,
            allClaims[_claimId].coverId,
            claimVote[_claimId],
            claimsStatus[_claimId],
            allClaims[_claimId].dateUpd,
            claimState12Count[_claimId]
            );
    }

    /**
     * @dev Gets the total number of votes of a given claim.
     * @param _claimId Claim Id.
     * @param _ca if 1: votes given by Claim Assessors to a claim,
     * else returns the number of votes of given by Members to a claim.
     * @return len total number of votes for/against a given claim.
     */ 
    function getClaimVoteLength(
        uint _claimId,
        uint8 _ca
    )
        external
        view
        returns(uint claimId, uint len)
    {
        claimId = _claimId;
        if (_ca == 1)
            len = claimVoteCA[_claimId].length;
        else
            len = claimVoteMember[_claimId].length;
    }

    /**
     * @dev Gets the verdict of a vote using claim id and index.
     * @param _ca 1 for vote given as a CA, else for vote given as a member.
     * @return ver 1 if vote was given in favour,-1 if given in against.
     */ 
    function getVoteVerdict(
        uint _claimId,
        uint _index,
        uint8 _ca
    )
        external
        view
        returns(int8 ver)
    {
        if (_ca == 1)
            ver = allvotes[claimVoteCA[_claimId][_index]].verdict;
        else
            ver = allvotes[claimVoteMember[_claimId][_index]].verdict;
    }

    /**
     * @dev Gets the Number of tokens of a vote using claim id and index.
     * @param _ca 1 for vote given as a CA, else for vote given as a member.
     * @return tok Number of tokens.
     */ 
    function getVoteToken(
        uint _claimId,
        uint _index,
        uint8 _ca
    )   
        external
        view
        returns(uint tok)
    {
        if (_ca == 1)
            tok = allvotes[claimVoteCA[_claimId][_index]].tokens;
        else
            tok = allvotes[claimVoteMember[_claimId][_index]].tokens;
    }

    /**
     * @dev Gets the Voter's address of a vote using claim id and index.
     * @param _ca 1 for vote given as a CA, else for vote given as a member.
     * @return voter Voter's address.
     */ 
    function getVoteVoter(
        uint _claimId,
        uint _index,
        uint8 _ca
    )
        external
        view
        returns(address voter)
    {
        if (_ca == 1)
            voter = allvotes[claimVoteCA[_claimId][_index]].voter;
        else
            voter = allvotes[claimVoteMember[_claimId][_index]].voter;
    }

    /** 
     * @dev Gets total number of Claims created by a user till date.
     * @param _add User's address.
     */ 
    function getUserClaimCount(address _add) external view returns(uint len) {
        len = allClaimsByAddress[_add].length;
    }

    /**
     * @dev Calculates number of Claims that are in pending state.
     */ 
    function getClaimLength() external view returns(uint len) {
        len = allClaims.length.sub(pendingClaimStart);
    }

    /**
     * @dev Gets the Number of all the Claims created till date.
     */ 
    function actualClaimLength() external view returns(uint len) {
        len = allClaims.length;
    }

    /** 
     * @dev Gets details of a claim.
     * @param _index claim id = pending claim start + given index
     * @param _add User's address.
     * @return coverid cover against which claim has been submitted.
     * @return claimId Claim  Id.
     * @return voteCA verdict of vote given as a Claim Assessor.  
     * @return voteMV verdict of vote given as a Member.
     * @return statusnumber Status of claim.
     */ 
    function getClaimFromNewStart(
        uint _index,
        address _add
    )
        external
        view
        returns(
            uint coverid,
            uint claimId,
            int8 voteCA,
            int8 voteMV,
            uint statusnumber
        )
    {
        uint i = pendingClaimStart.add(_index);
        coverid = allClaims[i].coverId;
        claimId = i;
        if (userClaimVoteCA[_add][i] > 0)
            voteCA = allvotes[userClaimVoteCA[_add][i]].verdict;
        else
            voteCA = 0;

        if (userClaimVoteMember[_add][i] > 0)
            voteMV = allvotes[userClaimVoteMember[_add][i]].verdict;
        else
            voteMV = 0;

        statusnumber = claimsStatus[i];
    }

    /**
     * @dev Gets details of a claim of a user at a given index.  
     */ 
    function getUserClaimByIndex(
        uint _index,
        address _add
    )
        external
        view
        returns(
            uint status,
            uint coverid,
            uint claimId
        )
    {
        claimId = allClaimsByAddress[_add][_index];
        status = claimsStatus[claimId];
        coverid = allClaims[claimId].coverId;
    }

    /**
     * @dev Gets Id of all the votes given to a claim.
     * @param _claimId Claim Id.
     * @return ca id of all the votes given by Claim assessors to a claim.
     * @return mv id of all the votes given by members to a claim.
     */ 
    function getAllVotesForClaim(
        uint _claimId
    )
        external
        view
        returns(
            uint claimId,
            uint[] memory ca,
            uint[] memory mv
        )
    {
        return (_claimId, claimVoteCA[_claimId], claimVoteMember[_claimId]);
    }

    /** 
     * @dev Gets Number of tokens deposit in a vote using
     * Claim assessor's address and claim id.
     * @return tokens Number of deposited tokens.
     */ 
    function getTokensClaim(
        address _of,
        uint _claimId
    )
        external
        view
        returns(
            uint claimId,
            uint tokens
        )
    {
        return (_claimId, allvotes[userClaimVoteCA[_of][_claimId]].tokens);
    }

    /**
     * @param _voter address of the voter.
     * @return lastCAvoteIndex last index till which reward was distributed for CA
     * @return lastMVvoteIndex last index till which reward was distributed for member
     */ 
    function getRewardDistributedIndex(
        address _voter
    ) 
        external
        view
        returns(
            uint lastCAvoteIndex,
            uint lastMVvoteIndex
        )
    {
        return (
            voterVoteRewardReceived[_voter].lastCAvoteIndex,
            voterVoteRewardReceived[_voter].lastMVvoteIndex
        );
    }

    /**
     * @param claimid claim id.
     * @return perc_CA reward Percentage for claim assessor
     * @return perc_MV reward Percentage for members
     * @return tokens total tokens to be rewarded 
     */ 
    function getClaimRewardDetail(
        uint claimid
    ) 
        external
        view
        returns(
            uint percCA,
            uint percMV,
            uint tokens
        )
    {
        return (
            claimRewardDetail[claimid].percCA,
            claimRewardDetail[claimid].percMV,
            claimRewardDetail[claimid].tokenToBeDist
        );
    }

    /**
     * @dev Gets cover id of a claim.
     */ 
    function getClaimCoverId(uint _claimId) external view returns(uint claimId, uint coverid) {
        return (_claimId, allClaims[_claimId].coverId);
    }

    /**
     * @dev Gets total number of tokens staked during voting by Claim Assessors.
     * @param _claimId Claim Id.
     * @param _verdict 1 to get total number of accept tokens, -1 to get total number of deny tokens.
     * @return token token Number of tokens(either accept or deny on the basis of verdict given as parameter).
     */ 
    function getClaimVote(uint _claimId, int8 _verdict) external view returns(uint claimId, uint token) {
        claimId = _claimId;
        token = 0;
        for (uint i = 0; i < claimVoteCA[_claimId].length; i++) {
            if (allvotes[claimVoteCA[_claimId][i]].verdict == _verdict)
                token = token.add(allvotes[claimVoteCA[_claimId][i]].tokens);
        }
    }

    /**
     * @dev Gets total number of tokens staked during voting by Members.
     * @param _claimId Claim Id.
     * @param _verdict 1 to get total number of accept tokens,
     *  -1 to get total number of deny tokens.
     * @return token token Number of tokens(either accept or 
     * deny on the basis of verdict given as parameter).
     */ 
    function getClaimMVote(uint _claimId, int8 _verdict) external view returns(uint claimId, uint token) {
        claimId = _claimId;
        token = 0;
        for (uint i = 0; i < claimVoteMember[_claimId].length; i++) {
            if (allvotes[claimVoteMember[_claimId][i]].verdict == _verdict)
                token = token.add(allvotes[claimVoteMember[_claimId][i]].tokens);
        }
    }

    /**
     * @param _voter address  of voteid
     * @param index index to get voteid in CA
     */ 
    function getVoteAddressCA(address _voter, uint index) external view returns(uint) {
        return voteAddressCA[_voter][index];
    }

    /**
     * @param _voter address  of voter
     * @param index index to get voteid in member vote
     */ 
    function getVoteAddressMember(address _voter, uint index) external view returns(uint) {
        return voteAddressMember[_voter][index];
    }

    /**
     * @param _voter address  of voter   
     */ 
    function getVoteAddressCALength(address _voter) external view returns(uint) {
        return voteAddressCA[_voter].length;
    }

    /**
     * @param _voter address  of voter   
     */ 
    function getVoteAddressMemberLength(address _voter) external view returns(uint) {
        return voteAddressMember[_voter].length;
    }

    /**
     * @dev Gets the Final result of voting of a claim.
     * @param _claimId Claim id.
     * @return verdict 1 if claim is accepted, -1 if declined.
     */ 
    function getFinalVerdict(uint _claimId) external view returns(int8 verdict) {
        return claimVote[_claimId];
    }

    /**
     * @dev Get number of Claims queued for submission during emergency pause.
     */ 
    function getLengthOfClaimSubmittedAtEP() external view returns(uint len) {
        len = claimPause.length;
    }

    /**
     * @dev Gets the index from which claim needs to be 
     * submitted when emergency pause is swithched off.
     */ 
    function getFirstClaimIndexToSubmitAfterEP() external view returns(uint indexToSubmit) {
        indexToSubmit = claimPauseLastsubmit;
    }
    
    /**
     * @dev Gets number of Claims to be reopened for voting post emergency pause period.
     */ 
    function getLengthOfClaimVotingPause() external view returns(uint len) {
        len = claimPauseVotingEP.length;
    }

    /**
     * @dev Gets claim details to be reopened for voting after emergency pause.
     */ 
    function getPendingClaimDetailsByIndex(
        uint _index
    )
        external
        view
        returns(
            uint claimId,
            uint pendingTime,
            bool voting
        )
    {
        claimId = claimPauseVotingEP[_index].claimid;
        pendingTime = claimPauseVotingEP[_index].pendingTime;
        voting = claimPauseVotingEP[_index].voting;
    }

    /** 
     * @dev Gets the index from which claim needs to be reopened when emergency pause is swithched off.
     */ 
    function getFirstClaimIndexToStartVotingAfterEP() external view returns(uint firstindex) {
        firstindex = claimStartVotingFirstIndex;
    }

    /**
     * @dev Updates Uint Parameters of a code
     * @param code whose details we want to update
     * @param val value to set
     */
    function updateUintParameters(bytes8 code, uint val) public {
        require(ms.checkIsAuthToGoverned(msg.sender));
        if (code == "CAMAXVT") {
            _setMaxVotingTime(val * 1 hours);

        } else if (code == "CAMINVT") {

            _setMinVotingTime(val * 1 hours);

        } else if (code == "CAPRETRY") {

            _setPayoutRetryTime(val * 1 hours);

        } else if (code == "CADEPT") {

            _setClaimDepositTime(val * 1 days);

        } else if (code == "CAREWPER") {

            _setClaimRewardPerc(val);

        } else if (code == "CAMINTH") {

            _setMinVoteThreshold(val);

        } else if (code == "CAMAXTH") {

            _setMaxVoteThreshold(val);

        } else if (code == "CACONPER") {

            _setMajorityConsensus(val);

        } else if (code == "CAPAUSET") {
            _setPauseDaysCA(val * 1 days);
        } else {

            revert("Invalid param code");
        }
    
    }

    /**
     * @dev Iupgradable Interface to update dependent contract address
     */
    function changeDependentContractAddress() public onlyInternal {}

    /**
     * @dev Adds status under which a claim can lie.
     * @param percCA reward percentage for claim assessor
     * @param percMV reward percentage for members
     */
    function _pushStatus(uint percCA, uint percMV) internal {
        rewardStatus.push(ClaimRewardStatus(percCA, percMV));
    }

    /**
     * @dev adds reward incentive for all possible claim status for Claim assessors and members
     */
    function _addRewardIncentive() internal {
        _pushStatus(0, 0); //0  Pending-Claim Assessor Vote
        _pushStatus(0, 0); //1 Pending-Claim Assessor Vote Denied, Pending Member Vote
        _pushStatus(0, 0); //2 Pending-CA Vote Threshold not Reached Accept, Pending Member Vote
        _pushStatus(0, 0); //3 Pending-CA Vote Threshold not Reached Deny, Pending Member Vote
        _pushStatus(0, 0); //4 Pending-CA Consensus not reached Accept, Pending Member Vote
        _pushStatus(0, 0); //5 Pending-CA Consensus not reached Deny, Pending Member Vote
        _pushStatus(100, 0); //6 Final-Claim Assessor Vote Denied
        _pushStatus(100, 0); //7 Final-Claim Assessor Vote Accepted
        _pushStatus(0, 100); //8 Final-Claim Assessor Vote Denied, MV Accepted
        _pushStatus(0, 100); //9 Final-Claim Assessor Vote Denied, MV Denied
        _pushStatus(0, 0); //10 Final-Claim Assessor Vote Accept, MV Nodecision
        _pushStatus(0, 0); //11 Final-Claim Assessor Vote Denied, MV Nodecision
        _pushStatus(0, 0); //12 Claim Accepted Payout Pending
        _pushStatus(0, 0); //13 Claim Accepted No Payout 
        _pushStatus(0, 0); //14 Claim Accepted Payout Done
    }

    /**
     * @dev Sets Maximum time(in seconds) for which claim assessment voting is open
     */ 
    function _setMaxVotingTime(uint _time) internal {
        maxVotingTime = _time;
    }

    /**
     *  @dev Sets Minimum time(in seconds) for which claim assessment voting is open
     */ 
    function _setMinVotingTime(uint _time) internal {
        minVotingTime = _time;
    }

    /**
     *  @dev Sets Minimum vote threshold required
     */ 
    function _setMinVoteThreshold(uint val) internal {
        minVoteThreshold = val;
    }

    /**
     *  @dev Sets Maximum vote threshold required
     */ 
    function _setMaxVoteThreshold(uint val) internal {
        maxVoteThreshold = val;
    }
    
    /**
     *  @dev Sets the value considered as Majority Consenus in voting
     */ 
    function _setMajorityConsensus(uint val) internal {
        majorityConsensus = val;
    }

    /**
     * @dev Sets the payout retry time
     */ 
    function _setPayoutRetryTime(uint _time) internal {
        payoutRetryTime = _time;
    }

    /**
     *  @dev Sets percentage of reward given for claim assessment
     */ 
    function _setClaimRewardPerc(uint _val) internal {

        claimRewardPerc = _val;
    }
  
    /** 
     * @dev Sets the time for which claim is deposited.
     */ 
    function _setClaimDepositTime(uint _time) internal {

        claimDepositTime = _time;
    }

    /**
     *  @dev Sets number of days claim assessment will be paused
     */ 
    function _setPauseDaysCA(uint val) internal {
        pauseDaysCA = val;
    }
}
function setClaimAtEmergencyPause(
    uint _coverId,
    uint _dateUpd,
    bool _submit
)
    external
    onlyInternal
{
    claimPause.push(ClaimsPause(_coverId, _dateUpd, _submit));
}

/** 
 @dev Queues Claims during Emergency Pause.
 */