// Copyright (C) 2012 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.gerrit.httpd.plugins;

import com.google.common.collect.Maps;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Version;
import com.google.gerrit.server.plugins.Plugin;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;

class PluginServletContext {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  static ServletContext create(Plugin plugin, String contextPath) {
    return (ServletContext)
        Proxy.newProxyInstance(
            PluginServletContext.class.getClassLoader(),
            new Class<?>[] {ServletContext.class, API.class},
            new Handler(plugin, contextPath));
  }

  private PluginServletContext() {}

  private static class Handler implements InvocationHandler, API {
    private final Plugin plugin;
    private final String contextPath;
    private final ConcurrentMap<String, Object> attributes;

    Handler(Plugin plugin, String contextPath) {
      this.plugin = plugin;
      this.contextPath = contextPath;
      this.attributes = Maps.newConcurrentMap();
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      Method handler;
      try {
        handler = API.class.getDeclaredMethod(method.getName(), method.getParameterTypes());
      } catch (NoSuchMethodException e) {
        throw new NoSuchMethodError(
            String.format(
                "%s does not implement %s", PluginServletContext.class, method.toGenericString()));
      }
      return handler.invoke(this, args);
    }

    @Override
    public String getContextPath() {
      return contextPath;
    }

    @Override
    public String getInitParameter(String name) {
      return null;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Enumeration getInitParameterNames() {
      return Collections.enumeration(Collections.emptyList());
    }

    @Override
    public ServletContext getContext(String name) {
      return null;
    }

    @Override
    public RequestDispatcher getNamedDispatcher(String name) {
      return null;
    }

    @Override
    public RequestDispatcher getRequestDispatcher(String name) {
      return null;
    }

    @Override
    public URL getResource(String name) {
      return null;
    }

    @Override
    public InputStream getResourceAsStream(String name) {
      return null;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Set getResourcePaths(String name) {
      return null;
    }

    @Override
    public Servlet getServlet(String name) {
      return null;
    }

    @Override
    public String getRealPath(String name) {
      return null;
    }

    @Override
    public String getServletContextName() {
      return plugin.getName();
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Enumeration getServletNames() {
      return Collections.enumeration(Collections.emptyList());
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Enumeration getServlets() {
      return Collections.enumeration(Collections.emptyList());
    }

    @Override
    public void log(Exception reason, String msg) {
      log(msg, reason);
    }

    @Override
    public void log(String msg) {
      log(msg, null);
    }

    @Override
    public void log(String msg, Throwable reason) {
      logger.atWarning().withCause(reason).log("[plugin %s] %s", plugin.getName(), msg);
    }

    @Override
    public Object getAttribute(String name) {
      return attributes.get(name);
    }

    @Override
    public Enumeration<String> getAttributeNames() {
      return Collections.enumeration(attributes.keySet());
    }

    @Override
    public void setAttribute(String name, Object value) {
      attributes.put(name, value);
    }

    @Override
    public void removeAttribute(String name) {
      attributes.remove(name);
    }

    @Override
    public String getMimeType(String file) {
      return null;
    }

    @Override
    public int getMajorVersion() {
      return 2;
    }

    @Override
    public int getMinorVersion() {
      return 5;
    }

    @Override
    public String getServerInfo() {
      String v = Version.getVersion();
      return "Gerrit Code Review/" + (v != null ? v : "dev");
    }
  }

  interface API {
    String getContextPath();

    String getInitParameter(String name);

    @SuppressWarnings("rawtypes")
    Enumeration getInitParameterNames();

    ServletContext getContext(String name);

    RequestDispatcher getNamedDispatcher(String name);

    RequestDispatcher getRequestDispatcher(String name);

    URL getResource(String name);

    InputStream getResourceAsStream(String name);

    @SuppressWarnings("rawtypes")
    Set getResourcePaths(String name);

    Servlet getServlet(String name);

    String getRealPath(String name);

    String getServletContextName();

    @SuppressWarnings("rawtypes")
    Enumeration getServletNames();

    @SuppressWarnings("rawtypes")
    Enumeration getServlets();

    void log(Exception reason, String msg);

    void log(String msg);

    void log(String msg, Throwable reason);

    Object getAttribute(String name);

    Enumeration<String> getAttributeNames();

    void setAttribute(String name, Object value);

    void removeAttribute(String name);

    String getMimeType(String file);

    int getMajorVersion();

    int getMinorVersion();

    String getServerInfo();
  }
}
