/*
 * Copyright (c) 2014, 2015 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.oomph.util;

import org.eclipse.oomph.internal.util.UtilPlugin;

import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.util.ResourceLocator;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
import org.w3c.dom.Element;

import javax.xml.parsers.DocumentBuilder;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

/**
 * @author Eike Stepper
 */
public abstract class OomphPlugin extends EMFPlugin
{
  protected OomphPlugin(ResourceLocator[] delegateResourceLocators)
  {
    super(delegateResourceLocators);
  }

  public final boolean isOSGiRunning()
  {
    return getEclipsePlugin() != null;
  }

  protected Plugin getEclipsePlugin()
  {
    return (Plugin)getPluginResourceLocator();
  }

  public final Bundle getBundle()
  {
    return getEclipsePlugin().getBundle();
  }

  public final BundleContext getBundleContext()
  {
    return getBundle().getBundleContext();
  }

  public final List<File> getClassPath() throws Exception
  {
    Bundle bundle = getBundle();
    return getClassPath(bundle);
  }

  public final IPath getStateLocation() throws IllegalStateException
  {
    return getEclipsePlugin().getStateLocation();
  }

  public final IPath getUserLocation() throws IllegalStateException
  {
    return new Path(PropertiesUtil.USER_HOME).append(".eclipse").append(getSymbolicName());
  }

  public final Preferences getInstancePreferences()
  {
    return getPreferences("instance");
  }

  public final Preference getInstancePreference(String key)
  {
    return new Preference(getInstancePreferences(), key);
  }

  public final Preferences getConfigurationPreferences()
  {
    return getPreferences("configuration");
  }

  public final Preference getConfigurationPreference(String key)
  {
    return new Preference(getConfigurationPreferences(), key);
  }

  private Preferences getPreferences(String scope)
  {
    IEclipsePreferences rootNode = Platform.getPreferencesService().getRootNode();
    Preferences instanceScope = rootNode.node(scope);
    return instanceScope.node(getSymbolicName());
  }

  public final boolean isDebugging()
  {
    return getEclipsePlugin().isDebugging();
  }

  public final void setDebugging(boolean value)
  {
    getEclipsePlugin().setDebugging(value);
  }

  public final <T> T getService(Class<T> serviceClass)
  {
    return ServiceUtil.getService(getBundleContext(), serviceClass);
  }

  public final void ungetService(Object service)
  {
    ServiceUtil.ungetService(getBundleContext(), service);
  }

  public final ILog getLog()
  {
    Plugin eclipsePlugin = getEclipsePlugin();
    if (eclipsePlugin == null)
    {
      return new ILog()
      {
        public void removeLogListener(ILogListener listener)
        {
        }

        public void log(IStatus status)
        {
          System.out.println(status);
        }

        public Bundle getBundle()
        {
          return null;
        }

        public void addLogListener(ILogListener listener)
        {
        }
      };
    }

    return eclipsePlugin.getLog();
  }

  public final void log(String message, int severity)
  {
    log(new Status(severity, getSymbolicName(), message));
  }

  public final void log(String message)
  {
    log(message, IStatus.INFO);
  }

  public final void log(IStatus status)
  {
    getLog().log(status);
  }

  public final void log(Throwable t, int severity)
  {
    log(getStatus(t, severity));
  }

  public final String log(Throwable t)
  {
    t.printStackTrace();

    IStatus status = getStatus(t);
    log(status);
    return status.getMessage();
  }

  public final IStatus getStatus(Object obj)
  {
    if (obj instanceof CoreException)
    {
      CoreException coreException = (CoreException)obj;
      return coreException.getStatus();
    }

    if (obj instanceof Throwable)
    {
      Throwable t = (Throwable)obj;
      return getStatus(t, IStatus.ERROR);
    }

    return new Status(IStatus.INFO, getSymbolicName(), obj.toString(), null);
  }

  public final IStatus getStatus(Throwable t, int severity)
  {
    String msg = t.getLocalizedMessage();
    if (msg == null || msg.length() == 0)
    {
      msg = t.getClass().getName();
    }

    return new Status(severity, getSymbolicName(), msg, t);
  }

  public final void coreException(IStatus status) throws CoreException
  {
    if (status != null)
    {
      int severity = status.getSeverity();
      if (severity == IStatus.CANCEL)
      {
        throw new OperationCanceledException();
      }

      if (severity == IStatus.ERROR)
      {
        throw new CoreException(status);
      }

      if (!status.isOK())
      {
        log(status);
      }
    }
  }

  public final void coreException(Throwable t) throws CoreException
  {
    if (t instanceof CoreException)
    {
      CoreException ex = (CoreException)t;
      IStatus status = ex.getStatus();
      if (status != null && status.getSeverity() == IStatus.CANCEL)
      {
        throw new OperationCanceledException();
      }

      throw ex;
    }

    if (t instanceof OperationCanceledException)
    {
      throw (OperationCanceledException)t;
    }

    if (t instanceof Error)
    {
      throw (Error)t;
    }

    IStatus status = getStatus(t);
    throw new CoreException(status);
  }

  public final String getBuildID()
  {
    Bundle bundle = getBundle();
    return getBuildID(bundle);
  }

  public final BundleFile getRootFile()
  {
    return new BundleFile.Root(getBundle());
  }

  public final File exportResources(String entry)
  {
    Bundle bundle = getBundle();
    File target = new File(PropertiesUtil.getProperty("java.io.tmpdir"), bundle.getSymbolicName() + "_" + bundle.getVersion());
    if (!target.exists())
    {
      exportResources(entry, target);
    }

    return target;
  }

  public final void exportResources(String entry, File target)
  {
    Bundle bundle = getBundle();
    exportResources(bundle, entry, target);
  }

  private static void exportResources(Bundle bundle, String entry, File target)
  {
    exportResources(bundle, entry.length(), entry, target.getAbsolutePath() + "/");
  }

  private static void exportResources(Bundle bundle, int sourceRootLength, String entry, String targetRoot)
  {
    File file = new File(targetRoot + entry.substring(sourceRootLength));

    if (entry.endsWith("/"))
    {
      file.mkdirs();

      String path = entry.substring(0, entry.length() - 1);
      Enumeration<String> entries = bundle.getEntryPaths(path);
      if (entries != null)
      {
        while (entries.hasMoreElements())
        {
          String childEntry = entries.nextElement();
          exportResources(bundle, sourceRootLength, childEntry, targetRoot);
        }
      }
    }
    else
    {
      InputStream source = null;
      OutputStream target = null;

      try
      {
        URL url = bundle.getResource(entry);
        source = url.openStream();
        target = new FileOutputStream(file);

        IOUtil.copy(source, target);
      }
      catch (IOException ex)
      {
        throw new IORuntimeException(ex);
      }
      finally
      {
        IOUtil.closeSilent(source);
        IOUtil.closeSilent(target);
      }
    }
  }

  public static void checkCancelation(IProgressMonitor monitor)
  {
    if (monitor != null && monitor.isCanceled())
    {
      throw new OperationCanceledException();
    }
  }

  public static String toString(Throwable t)
  {
    return print(t);
  }

  public static String toString(IStatus status)
  {
    return print(status);
  }

  private static String print(Object object)
  {
    try
    {
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      PrintStream printStream = new PrintStream(out, false, "UTF-8");

      print(object, null, printStream, 0, 0);

      printStream.close();
      return new String(out.toByteArray(), "UTF-8");
    }
    catch (UnsupportedEncodingException ex)
    {
      return object.toString();
    }
  }

  private static void print(Object object, StackTraceElement[] extra, PrintStream stream, int level, int more)
  {
    if (object instanceof IStatus)
    {
      IStatus status = (IStatus)object;
      indent(stream, level);

      int severity = status.getSeverity();
      switch (severity)
      {
        case IStatus.OK:
          stream.print("OK");
          break;

        case IStatus.ERROR:
          stream.print("ERROR");
          break;

        case IStatus.WARNING:
          stream.print("WARNING");
          break;

        case IStatus.INFO:
          stream.print("INFO");
          break;

        case IStatus.CANCEL:
          stream.print("CANCEL");
          break;

        default:
          stream.print("severity=");
          stream.print(severity);
      }

      stream.print(": ");
      stream.print(status.getPlugin());

      stream.print(" code=");
      stream.print(status.getCode());

      stream.print(' ');
      stream.println(status.getMessage());

      Throwable t = status.getException();
      if (t != null)
      {
        print(t, null, stream, level, more);
      }
      else if (extra != null)
      {
        print(extra, null, stream, level, more);
      }

      for (IStatus child : status.getChildren())
      {
        print(child, null, stream, level + 1, more);
      }
    }
    else if (object instanceof CoreException)
    {
      CoreException ex = (CoreException)object;

      IStatus status = ex.getStatus();
      if (status.getException() == null)
      {
        extra = ex.getStackTrace();
      }

      print(status, extra, stream, level, more);
    }
    else if (object instanceof Throwable)
    {
      Throwable t = (Throwable)object;

      indent(stream, level);
      if (more != 0)
      {
        stream.print("Caused by: ");
      }

      stream.print(t.getClass().getName());

      String msg = t.getLocalizedMessage();
      if (msg != null && msg.length() != 0)
      {
        stream.print(": ");
        stream.print(msg);
      }

      stream.println();

      print(t.getStackTrace(), null, stream, level, more);

      Throwable cause = t.getCause();
      if (cause != null)
      {
        print(cause, null, stream, level, more + 1);
      }

      if (t instanceof InvocationTargetException)
      {
        Throwable targetException = ((InvocationTargetException)t).getTargetException();
        print(targetException, null, stream, level + 1, more);
      }
    }
    else if (object instanceof StackTraceElement[])
    {
      StackTraceElement[] stackTrace = (StackTraceElement[])object;
      for (int i = 0; i < stackTrace.length - more; i++)
      {
        indent(stream, level + 1);
        stream.print("at ");
        stream.println(stackTrace[i].toString());
      }

      if (more != 0)
      {
        indent(stream, level + 1);
        stream.print("... ");
        stream.print(more);
        stream.println(" more");
      }
    }
    else if (extra != null)
    {
      print(extra, null, stream, level, more);
    }
  }

  private static void indent(PrintStream stream, int level)
  {
    for (int i = 0; i < level; ++i)
    {
      stream.print("  ");
    }
  }

  public static List<File> getClassPath(Bundle bundle) throws Exception
  {
    final List<File> cp = new ArrayList<File>();

    final File file = FileLocator.getBundleFile(bundle);
    if (file.isFile())
    {
      if (file.getName().endsWith(".jar"))
      {
        cp.add(file);
      }
    }
    else if (file.isDirectory())
    {
      File classpathFile = new File(file, ".classpath");
      if (classpathFile.isFile())
      {
        DocumentBuilder documentBuilder = XMLUtil.createDocumentBuilder();
        Element rootElement = XMLUtil.loadRootElement(documentBuilder, classpathFile);
        XMLUtil.handleElementsByTagName(rootElement, "classpathentry", new XMLUtil.ElementHandler()
        {
          public void handleElement(Element element) throws Exception
          {
            if ("output".equals(element.getAttribute("kind")))
            {
              String path = element.getAttribute("path");
              cp.add(new File(file, path));
            }
          }
        });
      }
      else
      {
        cp.add(file);
      }
    }

    return cp;
  }

  public static String getBuildID(Bundle bundle)
  {
    URL url = bundle.getResource("about.mappings");
    if (url != null)
    {
      InputStream source = null;

      try
      {
        source = url.openStream();

        Properties properties = new Properties();
        properties.load(source);

        String buildID = (String)properties.get("0");
        if (buildID != null && !buildID.startsWith("$"))
        {
          return buildID;
        }
      }
      catch (IOException ex)
      {
        //$FALL-THROUGH$
      }
      finally
      {
        IOUtil.closeSilent(source);
      }
    }

    return null;
  }

  /**
   * @author Eike Stepper
   */
  public static class BundleFile implements Comparable<BundleFile>
  {
    private static final List<BundleFile> NO_CHILDREN = Collections.emptyList();

    private String name;

    private boolean directory;

    private BundleFile parent;

    private List<BundleFile> children;

    protected BundleFile(String name, boolean directory, BundleFile parent)
    {
      this.name = name;
      this.directory = directory;
      this.parent = parent;
    }

    public Bundle getBundle()
    {
      return parent.getBundle();
    }

    public String getName()
    {
      return name;
    }

    public boolean isDirectory()
    {
      return directory;
    }

    public BundleFile getParent()
    {
      return parent;
    }

    public String getPath()
    {
      String path = parent.getPath();
      if (path.length() != 0)
      {
        path += "/";
      }

      return path + name;
    }

    public List<BundleFile> getChildren()
    {
      if (children == null)
      {
        children = new ArrayList<BundleFile>();

        Bundle bundle = getBundle();
        String path = "/" + getPath();
        Enumeration<String> paths = bundle.getEntryPaths(path);
        while (paths.hasMoreElements())
        {
          String childPath = paths.nextElement();

          boolean directory = childPath.endsWith("/");

          String childName = new Path(childPath).removeTrailingSeparator().lastSegment();
          BundleFile child = new BundleFile(childName, directory, this);
          children.add(child);
        }

        if (children.isEmpty())
        {
          children = NO_CHILDREN;
        }
        else
        {
          Collections.sort(children);
        }
      }

      return children;
    }

    public BundleFile getChild(String path)
    {
      String name;
      String remainder;

      int slash = path.indexOf('/');
      if (slash != -1)
      {
        name = path.substring(0, slash);
        remainder = path.substring(slash + 1);
      }
      else
      {
        name = path;
        remainder = null;
      }

      BundleFile child = null;
      for (BundleFile c : getChildren())
      {
        if (c.getName().equals(name))
        {
          child = c;
          break;
        }
      }

      if (child != null && remainder != null)
      {
        child = child.getChild(remainder);
      }

      return child;
    }

    public BundleFile addChild(String name, boolean directory) throws IOException
    {
      checkDirectory();

      BundleFile child = getChild(name);
      if (child != null)
      {
        throw new IllegalStateException("File already exists: " + child);
      }

      child = new BundleFile(name, directory, this);

      File file = new File(getFile(), name);
      if (directory)
      {
        file.mkdir();
      }
      else
      {
        file.createNewFile();
      }

      List<BundleFile> children = getChildren();
      children.add(child);
      Collections.sort(children);

      return child;
    }

    public void export(File target)
    {
      Bundle bundle = getBundle();
      String path = getPath();
      if (isDirectory())
      {
        path += "/";
      }

      exportResources(bundle, path, target);
    }

    public InputStream getContents()
    {
      checkFile();
      String path = getPath();
      URL url = getBundle().getEntry(path);

      InputStream in = null;

      try
      {
        return url.openStream();
      }
      catch (RuntimeException ex)
      {
        throw ex;
      }
      catch (Exception ex)
      {
        throw new RuntimeException(ex);
      }
      finally
      {
        IOUtil.closeSilent(in);
      }
    }

    public String getContentsString()
    {
      InputStream contents = getContents();
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      IOUtil.copy(contents, out);

      try
      {
        return out.toString("UTF-8");
      }
      catch (UnsupportedEncodingException ex)
      {
        throw new RuntimeException(ex);
      }
    }

    public void setContents(String contents)
    {
      checkFile();
      File file = getFile();

      OutputStream out = null;

      try
      {
        InputStream in = new ByteArrayInputStream(contents.getBytes("UTF-8"));
        out = new FileOutputStream(file);
        IOUtil.copy(in, out);
      }
      catch (RuntimeException ex)
      {
        throw ex;
      }
      catch (Exception ex)
      {
        throw new RuntimeException(ex);
      }
      finally
      {
        IOUtil.closeSilent(out);
      }
    }

    public int compareTo(BundleFile o)
    {
      return name.compareTo(o.getName());
    }

    @Override
    public String toString()
    {
      return getPath();
    }

    private void checkDirectory()
    {
      if (!directory)
      {
        throw new IllegalStateException("Should not be called on files");
      }
    }

    private void checkFile()
    {
      if (directory)
      {
        throw new IllegalStateException("Should not be called on directories");
      }
    }

    private File getFile()
    {
      String path = getPath();
      URL url = getBundle().getEntry(path);

      try
      {
        return new File(FileLocator.toFileURL(url).getFile());
      }
      catch (IOException ex)
      {
        throw new RuntimeException(ex);
      }
    }

    /**
     * @author Eike Stepper
     */
    private static class Root extends BundleFile
    {
      private Bundle bundle;

      public Root(Bundle bundle)
      {
        super("", true, null);
        if (bundle == null)
        {
          throw new IllegalArgumentException("Bundle is null");
        }

        this.bundle = bundle;
      }

      @Override
      public Bundle getBundle()
      {
        return bundle;
      }

      @Override
      public String getPath()
      {
        return "";
      }
    }
  }

  /**
   * @author Eike Stepper
   */
  public static class Preference
  {
    private final Preferences preferences;

    private final String key;

    public Preference(Preferences preferences, String key)
    {
      this.preferences = preferences;
      this.key = key;
    }

    public final Preferences preferences()
    {
      return preferences;
    }

    public final String key()
    {
      return key;
    }

    public void remove()
    {
      preferences.remove(key);
      flush();
    }

    public String get(String def)
    {
      return preferences.get(key, def);
    }

    public void set(String value)
    {
      preferences.put(key, value);
      flush();
    }

    public int get(int def)
    {
      return preferences.getInt(key, def);
    }

    public void set(int value)
    {
      preferences.putInt(key, value);
      flush();
    }

    public long get(long def)
    {
      return preferences.getLong(key, def);
    }

    public void set(long value)
    {
      preferences.putLong(key, value);
      flush();
    }

    public boolean get(boolean def)
    {
      return preferences.getBoolean(key, def);
    }

    public void set(boolean value)
    {
      preferences.putBoolean(key, value);
      flush();
    }

    public float get(float def)
    {
      return preferences.getFloat(key, def);
    }

    public void set(float value)
    {
      preferences.putFloat(key, value);
      flush();
    }

    public double get(double def)
    {
      return preferences.getDouble(key, def);
    }

    public void set(double value)
    {
      preferences.putDouble(key, value);
      flush();
    }

    public byte[] get(byte[] def)
    {
      return preferences.getByteArray(key, def);
    }

    public void set(byte[] value)
    {
      preferences.putByteArray(key, value);
      flush();
    }

    @Override
    public String toString()
    {
      return getClass().getSimpleName() + "[" + key + "]";
    }

    private void flush()
    {
      try
      {
        preferences.flush();
      }
      catch (BackingStoreException ex)
      {
        UtilPlugin.INSTANCE.log(ex);
      }
    }
  }
}
