// Copyright (C) 2013 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.googlesource.gerrit.plugins.its.rtc.network;

import java.util.HashMap;

import org.apache.http.client.params.ClientPNames;
import org.apache.http.conn.params.ConnManagerPNames;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.eclipse.jgit.lib.Config;

import com.google.common.base.Objects;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;

@SuppressWarnings("deprecation")
public class RTCHttpParams implements HttpParams {
  private static interface ParameterParser {
    public Object parse(String value);
  }

  private static final ParameterParser TYPE_STRING = new ParameterParser() {
    @Override
    public Object parse(String value) {
      return value;
    }
  };

  private static final ParameterParser TYPE_LONG = new ParameterParser() {
    @Override
    public Object parse(String value) {
      if (value == null) {
        return null;
      } else {
        return Long.parseLong(value);
      }
    }
  };

  private static final ParameterParser TYPE_INT = new ParameterParser() {
    @Override
    public Object parse(String value) {
      if (value == null) {
        return null;
      } else {
        return Integer.parseInt(value);
      }
    }
  };

  private static final ParameterParser TYPE_BOOL = new ParameterParser() {
    @Override
    public Object parse(String value) {
      if (value == null) {
        return null;
      } else {
        return Boolean.parseBoolean(value);
      }
    }
  };

  private static final HashMap<String, ParameterParser> TYPES =
      new HashMap<>();
  static {

    TYPES.put(CoreConnectionPNames.SO_TIMEOUT, TYPE_INT);
    TYPES.put(CoreConnectionPNames.TCP_NODELAY, TYPE_BOOL);
    TYPES.put(CoreConnectionPNames.SOCKET_BUFFER_SIZE, TYPE_INT);
    TYPES.put(CoreConnectionPNames.SO_LINGER, TYPE_INT);
    TYPES.put(CoreConnectionPNames.SO_REUSEADDR, TYPE_BOOL);
    TYPES.put(CoreConnectionPNames.CONNECTION_TIMEOUT, TYPE_INT);
    TYPES.put(CoreConnectionPNames.STALE_CONNECTION_CHECK, TYPE_BOOL);
    TYPES.put(CoreConnectionPNames.MAX_LINE_LENGTH, TYPE_INT);
    TYPES.put(CoreConnectionPNames.MAX_HEADER_COUNT, TYPE_INT);
    TYPES.put(CoreConnectionPNames.MIN_CHUNK_LIMIT, TYPE_INT);
    TYPES.put(CoreConnectionPNames.SO_KEEPALIVE, TYPE_BOOL);

    TYPES.put(ClientPNames.HANDLE_REDIRECTS, TYPE_BOOL);
    TYPES.put(ClientPNames.REJECT_RELATIVE_REDIRECT, TYPE_BOOL);
    TYPES.put(ClientPNames.MAX_REDIRECTS, TYPE_INT);
    TYPES.put(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, TYPE_BOOL);
    TYPES.put(ClientPNames.HANDLE_AUTHENTICATION, TYPE_BOOL);
    TYPES.put(ClientPNames.CONN_MANAGER_TIMEOUT, TYPE_LONG);

    TYPES.put(CoreProtocolPNames.STRICT_TRANSFER_ENCODING, TYPE_BOOL);
    TYPES.put(CoreProtocolPNames.USE_EXPECT_CONTINUE, TYPE_BOOL);
    TYPES.put(CoreProtocolPNames.WAIT_FOR_CONTINUE, TYPE_INT);

    TYPES.put(ConnManagerPNames.TIMEOUT, TYPE_LONG);
    TYPES.put(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, TYPE_INT);
  }
  private final String pluginName;
  private Config config;

  @Inject
  public RTCHttpParams(@PluginName String pluginName, @GerritServerConfig Config config) {
    this.pluginName = pluginName;
    this.config = config;
  }

  private String getParamName(String name) {
    StringBuilder camelisedName = new StringBuilder();
    for (String namePart : name.split("[\\.-]")) {
      if (camelisedName.length() > 0) {
        camelisedName.append(Character.toUpperCase(namePart.charAt(0)));
        camelisedName.append(namePart.substring(1, namePart.length()));
      } else {
        camelisedName.append(namePart);
      }
    }
    return camelisedName.toString();
  }

  @Override
  public Object getParameter(String name) {
    String value =
        config.getString(pluginName, null, getParamName(name));
    return getParameterParser(name).parse(value);
  }

  private ParameterParser getParameterParser(String name) {
    return Objects.firstNonNull(TYPES.get(name), TYPE_STRING);
  }

  @Override
  public HttpParams setParameter(String name, Object value) {
    return throwsNotSupported(HttpParams.class);
  }

  private <T> T throwsNotSupported(Class<T> clazz) {
    throw new IllegalArgumentException("Method not supported");
  }

  @Override
  @Deprecated
  public HttpParams copy() {
    return throwsNotSupported(HttpParams.class);
  }

  @Override
  public boolean removeParameter(String name) {
    return throwsNotSupported(Boolean.class);
  }

  @Override
  public long getLongParameter(String name, long defaultValue) {
    return config.getLong(pluginName, null, getParamName(name),
        defaultValue);
  }

  @Override
  public HttpParams setLongParameter(String name, long value) {
    return throwsNotSupported(HttpParams.class);
  }

  @Override
  public int getIntParameter(String name, int defaultValue) {
    return config.getInt(pluginName, null, getParamName(name),
        defaultValue);
  }

  @Override
  public HttpParams setIntParameter(String name, int value) {
    return throwsNotSupported(HttpParams.class);
  }

  @Override
  public double getDoubleParameter(String name, double defaultValue) {
    return throwsNotSupported(Double.class);
  }

  @Override
  public HttpParams setDoubleParameter(String name, double value) {
    return throwsNotSupported(HttpParams.class);
  }

  @Override
  public boolean getBooleanParameter(String name, boolean defaultValue) {
    return config.getBoolean(pluginName, null,
        getParamName(name), defaultValue);
  }

  @Override
  public HttpParams setBooleanParameter(String name, boolean value) {
    return throwsNotSupported(HttpParams.class);
  }

  @Override
  public boolean isParameterTrue(String name) {
    return getBooleanParameter(name, false);
  }

  @Override
  public boolean isParameterFalse(String name) {
    return !isParameterTrue(name);
  }
}
