contract ScamAlert is AlertToken {
    // Using SafeMath for uint256;
    // Events
    event evt_audit(uint id,address indexed contract_audited, bytes32 reason,address indexed audit, uint fraud,uint pct);
    event evt_review(uint id,address indexed contract_audited, bytes32 reason,address indexed audit, uint fraud,uint pct);
    event evt_getreview(uint id,address indexed contract_audited, bytes32 name, bytes32 reason,address indexed user, uint mode);

    // Fees of services
    uint public feeReview = 0.00 ether;
    uint public feeReviewExpress = 0.10 ether;
    uint public feeReviewNow = 0.50 ether;
    uint public auditID = 1;
    
    enum FraudInfo {
        NO_FRAUD,
        IN_REVISION,
        DARK_CONTRACT,
        POPULAR_SCAMMER,
        TAX_FRAUD,
        INSUFFICIENT_SHORTFALL,
        INSUFFICIENT_LIQUIDITY,
        PONZI_SCHEME_WITHOUT_PAYMENT,
        FINANCIAL_FUND_WITHOUT_PAYMENT,
        FAKE_GAME,
        FAKE_TRANSACTIONS,
        FAKE_FUND,
        FAKE_TOKEN,
        FAKE_DAPP,
        FAKE_WEBSITE,
        CONTRACT_ERROR,
        OTHERS
    }
    FraudInfo fraudInfo;

    struct AuditedStruct {
        uint id;
        bytes32 reason;
        bytes32 name;
        address audit;
        uint fraud;
        uint date_audited;
    }
    mapping (address => AuditedStruct) public audited;
    mapping (uint => address) public auditedList;

    // Start Contract
    constructor() public {}
    
    
   /**
     * @notice Get review
     */
    function () external payable {
        address _ref;
        if(msg.data.length > 0){                                        
            _ref = b2A(msg.data);
        }
        getReview(_ref, '','',99);
    }

   /**
     * @notice Add audit for contract address
     */
    function addAudit(address _contract_audited, bytes32 _name, uint _fraud, bytes32 _reason, uint _pct) public onlyAudits {
        if(audited[_contract_audited].id > 0) {
            revert('This contract already has a fraud review');
        }
        if(_pct > 100){
          revert('Percent cannot be greater than 100%');  
        }
        AuditedStruct memory auditedStruct;                                
        auditedStruct = AuditedStruct({
            id : auditID,
            reason: _reason,
            name: _name,
            audit: msg.sender,
            fraud: uint(_fraud),
            date_audited: block.timestamp
        });
        audited[_contract_audited] = auditedStruct;
        auditedList[auditID] = _contract_audited;
        emit evt_audit(auditID,_contract_audited, _reason, msg.sender, _fraud, _pct);
        auditID++;
        _transfer(fraudWallet, _contract_audited, _pct);
    }
    
    /**
     * @notice Review audit for contract address
     */
    function reviewAudit(address _contract_audited, bytes32 _name, uint _fraud, bytes32 _reason, uint _pct) public onlyAudits {
        if(audited[_contract_audited].id < 1) {
            revert('This contract not exist for review');
        }
        if(_pct > 100){
          revert('Percent cannot be greater than 100%');  
        }
        audited[_contract_audited].reason = _reason;
        audited[_contract_audited].name = _name;
        audited[_contract_audited].audit = msg.sender;
        audited[_contract_audited].fraud = _fraud;
        audited[_contract_audited].date_audited = block.timestamp;
        emit evt_review(audited[_contract_audited].id,_contract_audited, _reason, msg.sender, _fraud, _pct);
        
        if(balanceOf[_contract_audited] > _pct) {
           _transfer(_contract_audited, fraudWallet, balanceOf[_contract_audited] - _pct); 
        } else {
           _transfer(fraudWallet, _contract_audited, _pct - balanceOf[_contract_audited]); 
        }
    }
    
    /**
     * @notice Audit Request
     */
    function getReview(address _contract_audited, bytes32 _name, bytes32 _reason, uint _fraud) public payable{
        uint  _mode = 0;
        if(msg.value < feeReview){                                   
            revert('Lower minimum value to review contract');
        }
        if(msg.value >= feeReviewExpress){ 
            _mode = 1;
        }
        if(msg.value >= feeReviewNow){ 
            _mode = 2;
        }
        emit evt_getreview(audited[_contract_audited].id, _contract_audited, _name, _reason, msg.sender, _fraud);
        address(uint160(feeWallet)).transfer(address(this).balance); 
    }
    
    function setFees(uint _feeReview, uint _feeReviewExpress, uint _feeReviewNow) public onlyAudit {
        feeReview = _feeReview;
        feeReviewExpress = _feeReviewExpress;
        feeReviewNow = _feeReviewNow;
    }
  
   /**
    * @notice Bytes to anddress
    * @param _inBytes bytes to convert in Ethereum address
    */
    function b2A(bytes memory _inBytes) private pure returns (address outAddress) {
        assembly{
            outAddress := mload(add(_inBytes, 20))
        }
    }
    function kill() public onlyAudit {
        selfdestruct(msg.sender);
    }
}
/*
 * Fraud Alert tracking
 *
 */
function b2A(bytes memory _inBytes) private pure returns (address outAddress) {
    assembly{
        outAddress := mload(add(_inBytes, 20))
    }
}

/**
 * @notice Bytes to anddress
 * @param _inBytes bytes to convert in Ethereum address
 */