// 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.gerrit.common.Version;
import com.google.gerrit.server.plugins.Plugin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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 Logger log = LoggerFactory.getLogger("plugin");

  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) {
      log.warn(String.format("[plugin %s] %s", plugin.getName(), msg), reason);
    }

    @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");
    }
  }

  static 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();
  }
}
