package io.selendroid.standalone.server.handler;

import io.netty.handler.codec.http.HttpMethod;

import io.selendroid.standalone.server.BaseSelendroidStandaloneHandler;
import org.json.JSONException;
import org.json.JSONObject;

import io.selendroid.server.common.Response;
import io.selendroid.server.common.SelendroidResponse;
import io.selendroid.server.common.http.HttpRequest;
import io.selendroid.standalone.android.AndroidDevice;
import io.selendroid.standalone.android.KeyEvent;
import io.selendroid.standalone.android.impl.DefaultAndroidEmulator;
import io.selendroid.standalone.server.model.ActiveSession;
import io.selendroid.standalone.server.util.HttpClientUtil;

import java.util.logging.Level;
import java.util.logging.Logger;

public class NetworkConnectionHandler extends BaseSelendroidStandaloneHandler {
  private static final Logger log = Logger.getLogger(NetworkConnectionHandler.class.getName());

  public NetworkConnectionHandler(String mappedUri) {
    super(mappedUri);
  }

  @Override
  public Response handleRequest(HttpRequest request, JSONObject payload) throws JSONException {
    // Currently we only support changing the Airplane Mode setting
    // so we're going to only look at that bit of the ConnectionType.

    // check that we actually want to toggle the setting by getting the current airplane mode setting
    String sessionId = getSessionId(request);
    ActiveSession session = getActiveSession(request);
    // the URL happens to be the same, except we need to use GET instead of POST
    String url = "http://localhost:" + session.getSelendroidServerPort() + request.uri();
    Integer connectionType = getPayload(request).getJSONObject("parameters").getInt("type");
    try {
      JSONObject r = HttpClientUtil.parseJsonResponse(HttpClientUtil.executeRequest(url, HttpMethod.GET));
      // Airplane mode is the first bit, so even is disabled, odd is disabled
      if (r.getInt("value") % 2 == connectionType % 2) {
        // airplane modes are the same
        return new SelendroidResponse(sessionId, null);
      }
    } catch (Exception e) {
      log.log(Level.SEVERE, "Cannot change network connection", e);
      return new SelendroidResponse(sessionId, null);
    }

    Boolean airplaneMode = connectionType % 2 == 1;

    AndroidDevice device = getSelendroidDriver(request).getActiveSession(getSessionId(request)).getDevice();

    int deviceAPILevel = Integer.parseInt(device.getTargetPlatform().getApi());

    device.invokeActivity("android.settings.AIRPLANE_MODE_SETTINGS");

    // tap to make sure none of the selections are currently highlighted
    device.runAdbCommand("shell input tap 600 100");

    device.inputKeyevent(KeyEvent.KEYCODE_DPAD_DOWN);

    device.inputKeyevent(KeyEvent.KEYCODE_DPAD_CENTER);

    if (airplaneMode) {
      // adb connection needs a recycle when switching airplane mode on
      device.restartADB();
      // killing the server kills all the tcp forwards, need to re-establish them.
      for (ActiveSession activeSession : getSelendroidDriver(request).getActiveSessions()) {
        device.forwardPort(activeSession.getSelendroidServerPort(), activeSession.getSelendroidServerPort());
      }
    } else if (deviceAPILevel == 17 && device instanceof DefaultAndroidEmulator) {
      // data doesn't automatically get re-enabled when toggling it back on
      device.runAdbCommand("shell svc data disable");
      device.runAdbCommand("shell svc data enable");
    }


    // nice and magical, this will 'close' the settings view and reopen the last application, the one under test! :)
    if (deviceAPILevel >= 21) {
        //click default back button 3 times to get back to the app under test.  app > Settings > Network Settings
        device.inputKeyevent(KeyEvent.KEYCODE_BACK);
        device.inputKeyevent(KeyEvent.KEYCODE_BACK);
        device.inputKeyevent(KeyEvent.KEYCODE_BACK);
    } else {
        //click back button at the top of the Network Settings Activity
        device.inputKeyevent(KeyEvent.KEYCODE_DPAD_UP);
        device.inputKeyevent(KeyEvent.KEYCODE_DPAD_CENTER);
    }
    // airplane mode is 1, Data + WIFI is 6
    return new SelendroidResponse(sessionId, airplaneMode ? 1 : 6);
  }
}
