content: /*
   *  This file is part of LeagueLib.
   *  LeagueLib is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  LeagueLib is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with LeagueLib.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  package com.achimala.leaguelib.connection;
  
  import com.achimala.leaguelib.errors.*;
  import com.achimala.util.Callback;
  import com.gvaneyck.rtmp.LoLRTMPSClient;
  import com.gvaneyck.rtmp.TypedObject;
  
  import java.io.IOException;
  
  public class LeagueAccount {
      private LeagueServer _server;
      private String _clientVersion, _username, _password;
      LoLRTMPSClient _internalClient;
      
      /**
       * Creates a LeagueAccount, which is used to authenticate API calls to the League of Legends RTMP API.
       */
      public LeagueAccount(LeagueServer server, String clientVersion, String username, String password) {
          _server = server;
          _clientVersion = clientVersion;
          _username = username;
          _password = password;
      }
      
      private void setupClient() throws LeagueException {
          if(_server == null || _clientVersion == null || _username == null || _password == null || _username.length() <= 0 || _password.length() <= 0)
              throw new LeagueException(LeagueErrorCode.AUTHENTICATION_ERROR, "Missing credentials");
          if(_internalClient == null)
              _internalClient = new LoLRTMPSClient(_server.getServerCode(), _clientVersion, _username, _password);
      }
      
      /**
       * Returns true if this account is connected to the League of Legends RTMP server, or false otherwise.
       */
      public boolean isConnected() {
          return _internalClient != null && _internalClient.isConnected() && _internalClient.isLoggedIn();
      }
      
      /**
       * Attempts to connect this account to the League of Legends RTMP server.
       * Upon failure, throws a LeagueException
       * Connects synchronously. Upon returning, guarantees account is valid and connected.
       * If the account is already connected, has no effect.
       */
      public void connect() throws LeagueException {
          try {
              if(_internalClient == null)
                  setupClient();
              if(_internalClient.isConnected()) {
                  if(_internalClient.isLoggedIn())
                      return;
                  else
                      _internalClient.login();
              } else
                  _internalClient.connectAndLogin();
          } catch(IOException e) {
              throw new LeagueException(LeagueErrorCode.NETWORK_ERROR, e.getMessage());
          }
      }
      
      /**
       * Cleanly disconnects from the League of Legends RTMP server.
       * No effect if the account is not connected.
       * You should always remember to call this, because the LoL RTMP service expects a logout message.
       * Otherwise it will be in an inconsistent state until the heartbeat timeout kicks the user.
       */
      public void close() {
          if(!isConnected())
              return;
          _internalClient.close();
      }
      
      /**
       * Invokes an API call on the RTMP server.
       * Returns the raw packet data retrieved from the API call.
       * You should never have to call this method directly; create your accounts and create a LeagueConnection.
       * Then push your accounts onto the LeagueConnection's account queue.
       * You can then use LeagueConnection's invoke method or (preferably) use a League service abstraction.
       */
      public TypedObject invoke(String service, String method, Object arguments) throws LeagueException {
          if(!isConnected())
              throw new LeagueException(LeagueErrorCode.RTMP_ERROR, toString() + " is unable to connect to RTMP server");
          try {
              // System.out.println(_username + " performing " + method + " in " + service);
              return _internalClient.getResult(_internalClient.invoke(service, method, arguments));
          } catch(IOException e) {
              throw new LeagueException(LeagueErrorCode.NETWORK_ERROR, e.getMessage());
          }
      }
      
      /**
       * Same as invoke() but happens in a background thread, asynchronously. Returns immediately.
       * Suppresses exceptions and calls onError of the provided callback instead.
       * You shouldn't call this directly, but create a wrapping LeagueConnection and use its invokeWithCallback.
       */
      public void invokeWithCallback(String service, String method, Object arguments, final Callback<TypedObject> callback) {
          try {
              // System.out.println(_username + " performing " + method + " in " + service);
              _internalClient.invokeWithCallback(service, method, arguments, new com.gvaneyck.rtmp.Callback() {
                  public void callback(TypedObject result) {
                      callback.onCompletion(result);
                  }
              });
          } catch(IOException e) {
              callback.onError(e);
          }
      }
      
      public void setServer(LeagueServer server) {
          _server = server;
      }
      
      public void setClientVersion(String clientVersion) {
          _clientVersion = clientVersion;
      }
      
      public void setUsername(String username) {
          _username = username;
      }
      
      public void setPassword(String password) {
          _password = password;
      }
      
      public LeagueServer getServer() {
          return _server;
      }
      
      public String getClientVersion() {
          return _clientVersion;
      }
      
      public String getUsername() {
          return _username;
      }
      
      public String getPassword() {
          return _password;
      }
      
      public String toString() {
          return String.format("<LeagueAccount: %s on %s>", _username, _server.getServerCode());
      }
      
      public boolean equals(Object o) {
          if(!(o instanceof LeagueAccount))
              return false;
          LeagueAccount other = (LeagueAccount)o;
          return other.getServer() == _server && other.getUsername().equals(_username) && other.getPassword().equals(_password);
      }
  }