contract Operators is Ownership {
  // state variable
  address[] private operators;
  uint8 MAX_OP_LEVEL;
  mapping (address => uint8) operatorLevel; // mapping of address to level

  // events
  event OperatorAdded (address _operator, uint8 _level);
  event OperatorUpdated (address _operator, uint8 _level);
  event OperatorRemoved (address _operator);

  constructor()
    public
  {
    MAX_OP_LEVEL = 3;
  }

  modifier onlyLevel(uint8 level) {
    uint8 opLevel = getOperatorLevel(msg.sender);
    if (level > 0) {
      require( opLevel <= level && opLevel != 0);
      _;
    } else {
      _;
    }
  }

  modifier onlyValidLevel(uint8 _level){
    require(_level> 0 && _level <= MAX_OP_LEVEL);
    _;
  }

  function addOperator(address _newOperator, uint8 _level)
    public 
    onlyOwner
    whenNotPaused
    onlyValidLevel(_level)
    returns (bool)
  {
    require (operatorLevel[_newOperator] == 0); // use change level instead
    operatorLevel[_newOperator] = _level;
    operators.push(_newOperator);
    emit OperatorAdded(_newOperator, _level);
    return true;
  }

  function updateOperator(address _operator, uint8 _level)
    public
    onlyOwner
    whenNotPaused
    onlyValidLevel(_level)
    returns (bool)
  {
    require (operatorLevel[_operator] != 0); // use add Operator
    operatorLevel[_operator] = _level;
    emit OperatorUpdated(_operator, _level);
    return true;
  }

  function removeOperatorByIndex(uint index)
    public
    onlyOwner
    whenNotPaused
    returns (bool)
  {
    index = index - 1;
    operatorLevel[operators[index]] = 0;
    operators[index] = operators[operators.length - 1];
    operators.length -- ;
    return true;

  }

  
    /**
   * @dev Use removeOperatorByIndex instead to save gas
   * warning: not advised to use this function.
   */
  function removeOperator(address _operator)
    public
    onlyOwner
    whenNotPaused
    returns (bool)
  {
    uint index = getOperatorIndex(_operator);
    require(index > 0);
    return removeOperatorByIndex(index);
  }

  function getOperatorIndex(address _operator)
    public
    view
    returns (uint)
  {
    for (uint i=0; i<operators.length; i++) {
      if (operators[i] == _operator) return i+1;
    }
    return 0;
  }

  function getOperators()
    public
    view
    returns (address[] memory)
  {
    return operators;
  }

  function getOperatorLevel(address _operator)
    public
    view
    returns (uint8)
  {
    return operatorLevel[_operator];
  }

}
/**
 * @title Operators
 * @author Prashant Prabhakar Singh
 * This contract add functionlaity of adding operators that have higher authority than a normal user
 * @dev Operators can perform different actions based on their level.
 */
function removeOperator(address _operator)
  public
  onlyOwner
  whenNotPaused
  returns (bool)
{
  uint index = getOperatorIndex(_operator);
  require(index > 0);
  return removeOperatorByIndex(index);
}

/**
 * @dev Use removeOperatorByIndex instead to save gas
 * warning: not advised to use this function.
 */