// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.reviewit;

import android.app.AlertDialog;
import android.app.Fragment;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.TextView;

import com.google.common.base.Strings;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.reviewit.app.ConfigManager;
import com.google.reviewit.app.Preferences;
import com.google.reviewit.app.QueryConfig;
import com.google.reviewit.app.ServerConfig;
import com.google.reviewit.util.FormatUtil;
import com.google.reviewit.util.WidgetUtil;
import com.urswolfer.gerrit.client.rest.GerritAuthData;
import com.urswolfer.gerrit.client.rest.GerritRestApiFactory;
import com.urswolfer.gerrit.client.rest.http.HttpStatusException;

import java.net.MalformedURLException;
import java.net.URL;

import static com.google.reviewit.util.WidgetUtil.setGone;
import static com.google.reviewit.util.WidgetUtil.setInvisible;
import static com.google.reviewit.util.WidgetUtil.setVisible;

public class ServerSettingsFragment extends BaseFragment {
  private static final String TAG = ServerSettingsFragment.class.getName();
  private static final String ORIGIN =
      "com.google.reviewit.ServerSettingsFragment.ORIGIN";
  private static final String SERVER_ID =
      "com.google.reviewit.ServerSettingsFragment.SERVER_ID";

  public static ServerSettingsFragment create(
      Class<? extends Fragment> origin) {
    ServerSettingsFragment fragment = new ServerSettingsFragment();
    Bundle bundle = new Bundle();
    bundle.putSerializable(ORIGIN, origin);
    fragment.setArguments(bundle);
    return fragment;
  }

  public static ServerSettingsFragment create(
      Class<? extends Fragment> origin, String serverId) {
    ServerSettingsFragment fragment = new ServerSettingsFragment();
    Bundle bundle = new Bundle();
    bundle.putSerializable(ORIGIN, origin);
    bundle.putString(SERVER_ID, serverId);
    fragment.setArguments(bundle);
    return fragment;
  }

  @Override
  protected @LayoutRes int getLayout() {
    return R.layout.content_server_settings;
  }

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    init();
    String serverId = getArguments() != null
        ? getArguments().getString(SERVER_ID)
        : null;
    displayServerConfig(serverId != null ? getApp().getConfigManager()
        .getServerConfig(serverId) : null);
  }

  private void displayServerConfig(ServerConfig cfg) {
    if (cfg != null) {
      WidgetUtil.setText(v(R.id.idInput), cfg.id);
      WidgetUtil.setText(v(R.id.nameInput), cfg.name);
      WidgetUtil.setText(v(R.id.urlInput), cfg.url);
      WidgetUtil.setText(v(R.id.userInput), cfg.user);
      WidgetUtil.setText(v(R.id.passwordInput), cfg.password);

      displayCredentialsInfo(cfg.url);
    } else {
      WidgetUtil.setText(v(R.id.idInput), "");
      WidgetUtil.setText(v(R.id.nameInput), "");
      WidgetUtil.setText(v(R.id.urlInput), "");
      WidgetUtil.setText(v(R.id.userInput), "");
      WidgetUtil.setText(v(R.id.passwordInput), "");

      displayCredentialsInfo(null);
    }
  }

  private void init() {
    final AutoCompleteTextView urlInput =
        (AutoCompleteTextView) v(R.id.urlInput);
    ArrayAdapter<String> adapter =
        new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1,
            getResources().getStringArray(R.array.urls));
    urlInput.setAdapter(adapter);

    v(R.id.pasteCredentialsButton).setOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            ClipboardManager clipboard = (ClipboardManager) getActivity()
                .getSystemService(Context.CLIPBOARD_SERVICE);
            if (clipboard.hasPrimaryClip()
                && clipboard.getPrimaryClipDescription().hasMimeType(
                ClipDescription.MIMETYPE_TEXT_PLAIN)) {
              ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
              String pasteData = item.getText().toString();
              if (!pasteData.contains("/.gitcookies")) {
                return;
              }

              pasteData = pasteData.substring(pasteData.indexOf("/.gitcookies"));
              pasteData = pasteData.substring(pasteData.lastIndexOf(",") + 1);
              int pos = pasteData.indexOf("=");
              String user = pasteData.substring(0, pos);
              pasteData = pasteData.substring(pos + 1);
              String password = pasteData.substring(0, pasteData.indexOf("\n"));
              WidgetUtil.setText(v(R.id.userInput), user);
              WidgetUtil.setText(v(R.id.passwordInput), password);

              // hide keyboard if it is open
              View view = getActivity().getCurrentFocus();
              if (view != null) {
                ((InputMethodManager) getActivity().getSystemService(
                    Context.INPUT_METHOD_SERVICE))
                        .hideSoftInputFromWindow(view.getWindowToken(), 0);
              }
            }
          }
        });

    ((EditText) v(R.id.urlInput)).addTextChangedListener(new TextWatcher() {
      @Override
      public void beforeTextChanged(
          CharSequence s, int start, int count, int after) {
      }

      @Override
      public void onTextChanged(
          CharSequence s, int start, int before, int count) {
      }

      @Override
      public void afterTextChanged(Editable s) {
        if (Strings.isNullOrEmpty(textOf(R.id.nameInput))) {
          try {
            String host = new URL(s.toString()).getHost();
            int pos = host.indexOf(".");
            WidgetUtil.setText(v(R.id.nameInput),
                pos > 0
                    ? host.substring(0, pos)
                    : host);
          } catch (MalformedURLException e) {
            // ignore
          }
        }
        displayCredentialsInfo(s.toString());
      }
    });

    v(R.id.saveServerSettings).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        enabledForm(false);

        if (!isServerInputComplete()) {
          widgetUtil.showError(R.string.incompleteInput);
          enabledForm(true);
          return;
        }

        if (!isUrlValid()) {
          widgetUtil.showError(R.string.invalidUrl);
          enabledForm(true);
          return;
        }

        if (!hasUniqueName()) {
          widgetUtil.showError(
              getString(R.string.duplicate_server_name, textOf(R.id.nameInput)));
          enabledForm(true);
          return;
        }

        setVisible(
            v(R.id.statusTestConnection, R.id.statusTestConnectionProgress));
        WidgetUtil.setText(v(R.id.statusTestConnectionText), null);
        new AsyncTask<Void, Void, String>() {
          private TextView status;
          private View statusTestConnectionProgress;
          private View statusTestConnection;

          @Override
          protected void onPreExecute() {
            super.onPreExecute();
            status = tv(R.id.statusTestConnectionText);
            statusTestConnectionProgress = v(R.id.statusTestConnectionProgress);
            statusTestConnection = v(R.id.statusTestConnection);
          }

          @Override
          protected String doInBackground(Void... v) {
            return testConnection();
          }

          protected void onPostExecute(String errorMsg) {
            if (errorMsg != null) {
              enabledForm(true);
              status.setTextColor(widgetUtil.color(R.color.statusFailed));
              status.setText(getString(R.string.test_server_connection_failed));
              setInvisible(statusTestConnectionProgress);
              new AlertDialog.Builder(getContext())
                  .setTitle(getString(R.string.error_title))
                  .setMessage(getString(R.string.connection_failed, errorMsg))
                  .setPositiveButton(android.R.string.ok,
                      new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                          // do nothing
                        }
                      }).setNegativeButton(getString(R.string.save_anyway),
                  new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                      setGone(statusTestConnection);
                      onServerSave(saveServerSettings());
                    }
                  }).setIcon(android.R.drawable.ic_dialog_alert).show();
            } else {
              status.setTextColor(widgetUtil.color(R.color.statusOk));
              status.setText(getString(R.string.test_server_connection_ok));
              setGone(statusTestConnection);
              onServerSave(saveServerSettings());
            }
          }
        }.execute();
      }
    });

    enabledForm(true);
    setGone(v(R.id.statusTestConnection));
  }

  private void enabledForm(boolean enable) {
    v(R.id.urlInput).setEnabled(enable);
    v(R.id.nameInput).setEnabled(enable);
    v(R.id.pasteCredentialsButton).setEnabled(enable);
    v(R.id.userInput).setEnabled(enable);
    v(R.id.passwordInput).setEnabled(enable);
    v(R.id.saveServerSettings).setEnabled(enable);
  }

  private boolean isServerInputComplete() {
    return !Strings.isNullOrEmpty(textOf(R.id.urlInput))
        && !Strings.isNullOrEmpty(textOf(R.id.nameInput))
        && !Strings.isNullOrEmpty(textOf(R.id.userInput))
        && !Strings.isNullOrEmpty(textOf(R.id.passwordInput));
  }

  private boolean isUrlValid() {
    try {
      new URL(textOf(R.id.urlInput));
      return true;
    } catch (MalformedURLException e) {
      return false;
    }
  }

  private boolean hasUniqueName() {
    if (!Strings.isNullOrEmpty(textOf(R.id.idInput))) {
      // update of existing entry
      return true;
    }

    ServerConfig otherCfg =
        getApp().getConfigManager().getServerByName(textOf(R.id.nameInput));
    return otherCfg == null;
  }

  private String testConnection() {
    GerritApi api = new GerritRestApiFactory().create(
        new GerritAuthData.Basic(
            textOf(R.id.urlInput),
            textOf(R.id.userInput),
            textOf(R.id.passwordInput)));
    try {
      api.changes().query().withLimit(1).get();

      String version = api.config().server().getVersion();
      Log.i(TAG, "version of " + textOf(R.id.nameInput) + ": " + version);
      // TODO check server version (server must support labeled stars and
      // run notedb)
      return null;
    } catch (HttpStatusException e) {
      return e.getStatusCode() + " " + e.getStatusText();
    } catch (RestApiException e) {
      // server not reachable
      Log.e(TAG, "Request failed", e);
      if (e.getCause() != null) {
        return getString(R.string.error_with_cause, e.getMessage(),
            e.getCause().getMessage());
      } else {
        return e.getMessage();
      }
    }
  }

  private void onServerSave(String serverId) {
    if (getArguments().get(ORIGIN).equals(IntroFragment2.class)) {
      ConfigManager cfgManager = getApp().getConfigManager();
      cfgManager.setQueryConfig(
          new QueryConfig.Builder(cfgManager.getQueryConfig())
              .setServerId(serverId)
              .build());
      getApp().getPrefManager().setPreferences(
          new Preferences.Builder(getApp().getPrefManager().getPreferences())
              .setShowIntro(false)
              .build());
      startActivity(new Intent(getContext(), MainActivity.class));
    } else {
      display(ServerListFragment.class);
    }
  }

  private void displayCredentialsInfo(String url) {
    if (Strings.isNullOrEmpty(url)) {
      setGone(v(R.id.crendentialsInfo, R.id.credentialsInfoText,
          R.id.pasteCredentialsButton));
      return;
    }

    TextView credentialsInfo = (TextView) v(R.id.credentialsInfoText);
    credentialsInfo.setMovementMethod(LinkMovementMethod.getInstance());
    url = FormatUtil.ensureSlash(url);

    String host;
    try {
      host = new URL(url).getHost();
    } catch (MalformedURLException e) {
      setGone(v(R.id.crendentialsInfo, R.id.credentialsInfoText,
          R.id.pasteCredentialsButton));
      return;
    }

    if (host.endsWith(".googlesource.com")) {
      url += "new-password";
      credentialsInfo.setText(Html.fromHtml(
          getString(R.string.credentials_info_googlesource,
              createLink(url, getString(R.string.googlesource_obtain_password)))));
      setVisible(v(R.id.crendentialsInfo, R.id.credentialsInfoText,
          R.id.pasteCredentialsButton));
    } else {
      url += "#/settings/http-password";
      credentialsInfo.setText(Html.fromHtml(
          getString(R.string.credentials_info,
              createLink(url, getString(R.string.http_password)))));
      setGone(v(R.id.pasteCredentialsButton));
      setVisible(v(R.id.crendentialsInfo, R.id.credentialsInfoText));
    }
  }

  private String createLink(String url, String text) {
    return "<a href=\"" + url + "\">" + text + "</a>";
  }

  private String saveServerSettings() {
    return getApp().getConfigManager().setServerConfig(
        new ServerConfig.Builder()
            .setId(textOf(R.id.idInput))
            .setName(textOf(R.id.nameInput))
            .setUrl(textOf(R.id.urlInput))
            .setUser(textOf(R.id.userInput))
            .setPassword(textOf(R.id.passwordInput))
            .build());
  }
}
