/*
 * Copyright (c) 2019 Ed Merks and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *    Ed Merks - initial API and implementation
 */
package org.eclipse.oomph.setup.internal.installer;

import org.eclipse.oomph.internal.setup.SetupProperties;
import org.eclipse.oomph.util.IOUtil;
import org.eclipse.oomph.util.OS;
import org.eclipse.oomph.util.OomphPlugin.Preference;
import org.eclipse.oomph.util.PropertiesUtil;
import org.eclipse.oomph.util.ReflectUtil;
import org.eclipse.oomph.util.StringUtil;

import org.eclipse.emf.common.util.URI;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.urischeme.IOperatingSystemRegistration;
import org.eclipse.urischeme.IScheme;
import org.eclipse.urischeme.ISchemeInformation;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public final class URISchemeUtil
{
  private static final Preference PREF_WEB_LINKS = SetupInstallerPlugin.INSTANCE.getConfigurationPreference("web-links"); //$NON-NLS-1$

  private static final IOperatingSystemRegistration OPERATING_SYSTEM_REGISTRATION = ReflectUtil.invokeMethod("getInstance", IOperatingSystemRegistration.class); //$NON-NLS-1$

  private static final String INSTALLER_SCHEME = PropertiesUtil.getProperty(SetupProperties.PROP_SETUP_INSTALLER_URI_SCHEME + "installer", "eclipse+installer"); //$NON-NLS-1$ //$NON-NLS-2$

  private static final String MARKETPLACE_SCHEME = PropertiesUtil.getProperty(SetupProperties.PROP_SETUP_INSTALLER_URI_SCHEME + "mpc", "?"); //$NON-NLS-1$ //$NON-NLS-2$

  private static final String FAKE_ECLIPSE_HOME = PropertiesUtil.getProperty("oomph.setup.installer.uri.scheme.eclipse.home", null); //$NON-NLS-1$

  private static final Collection<IScheme> SCHEMES;

  static
  {
    Collection<IScheme> schemes = new ArrayList<>();
    for (final String scheme : new String[] { INSTALLER_SCHEME, MARKETPLACE_SCHEME })
    {
      if (URI.validScheme(scheme))
      {
        schemes.add(new IScheme()
        {
          @Override
          public String getName()
          {
            return scheme;
          }

          @Override
          public String getDescription()
          {
            return scheme;
          }
        });
      }
    }

    SCHEMES = schemes;
  }

  private URISchemeUtil()
  {
  }

  /**
   * Converts the argument to a URI, resolving the URI if it's one of the registered web link schemes.
   * It first tries to interpret the argument as a file system file, checking if that is really a file that can be read;
   * in that case it will yield a file: URI.
   * Otherwise it's interpreted as a URI, except on Windows if the result has a scheme with a single letter, in which case
   * it will also yield a file: URI.
   * If the URI uses a web link scheme, the URI is resolved to yield a normalized URI that can be used directly as normal.
   */
  public static URI getResourceURI(String argument)
  {
    try
    {
      File file = new File(argument);
      if (file.isFile() && file.canRead())
      {
        return URI.createFileURI(IOUtil.getCanonicalFile(file).toString());
      }
    }
    catch (Throwable ex)
    {
      //$FALL-THROUGH$
    }

    URI uri = URI.createURI(argument);
    String scheme = uri.scheme();
    if (scheme == null || OS.INSTANCE.isWin() && scheme.length() == 1)
    {
      uri = URI.createFileURI(IOUtil.getCanonicalFile(new File(argument)).toString());
    }

    if (INSTALLER_SCHEME.equals(uri.scheme()) && uri.opaquePart() != null)
    {
      uri = URI.createURI(uri.opaquePart()).appendQuery(uri.query()).appendFragment(uri.fragment());
    }

    return uri;
  }

  /**
   * Returns this installer's launcher, or the empty string.
   * The latter is always yielded for a debug launch.
   */
  public static String getSelfLauncher()
  {
    Runnable restore = setEclipseHome(FAKE_ECLIPSE_HOME);
    String eclipseLauncher = OPERATING_SYSTEM_REGISTRATION.getEclipseLauncher();
    if (restore != null)
    {
      restore.run();
    }
    return StringUtil.isEmpty(eclipseLauncher) || eclipseLauncher.startsWith("file:") ? "" : eclipseLauncher; //$NON-NLS-1$ //$NON-NLS-2$
  }

  private static Runnable setEclipseHome(String eclipseHome)
  {
    if (!StringUtil.isEmpty(eclipseHome))
    {
      final String originalHomeLocation = System.getProperty("eclipse.home.location"); //$NON-NLS-1$
      System.setProperty("eclipse.home.location", eclipseHome); //$NON-NLS-1$
      return new Runnable()
      {
        @Override
        public void run()
        {
          System.setProperty("eclipse.home.location", originalHomeLocation); //$NON-NLS-1$
        }
      };
    }

    return null;
  }

  /**
   * Registers this installer for any scheme that does not have a conflicting registration.
   */
  public static void registerDefault()
  {
    boolean isSet = PREF_WEB_LINKS.get((String)null) != null;
    if (!isSet && canRegister())
    {
      Map<String, String> conflictingRegistrations = getConflictingRegistrations();
      for (IScheme scheme : SCHEMES)
      {
        String schemeName = scheme.getName();
        if (!conflictingRegistrations.containsKey(schemeName))
        {
          setRegistrations(Collections.singletonMap(schemeName, getSelfLauncher()));
        }
      }
    }
  }

  /**
   * Returns true only if the registry is accessible, if the self launcher is known, and the installer is one at a permanent disk location.
   */
  private static boolean canRegister()
  {
    try
    {
      OPERATING_SYSTEM_REGISTRATION.getSchemesInformation(SCHEMES);
    }
    catch (Exception ex)
    {
      return false;
    }

    return !StringUtil.isEmpty(getSelfLauncher()) && !KeepInstallerUtil.canKeepInstaller();
  }

  /**
   * Returns true if there is at least one scheme is actually registered for this installer.
   */
  public static boolean isRegistered()
  {
    String eclipseLauncher = getSelfLauncher();
    if (StringUtil.isEmpty(eclipseLauncher))
    {
      return false;
    }

    try
    {
      List<ISchemeInformation> schemesInformation = OPERATING_SYSTEM_REGISTRATION.getSchemesInformation(SCHEMES);
      for (ISchemeInformation schemeInformation : schemesInformation)
      {
        String handlerInstanceLocation = schemeInformation.getHandlerInstanceLocation();
        if (eclipseLauncher.equals(handlerInstanceLocation))
        {
          return true;
        }
      }
    }
    catch (Exception ex)
    {
    }

    return false;
  }

  /**
   * Updates the specified registrations in the system registry.
   */
  public static void setRegistrations(Map<String, String> newRegistrations)
  {
    Map<String, String> existingRegistrations = getRegistrations();
    for (Map.Entry<String, String> entry : newRegistrations.entrySet())
    {
      String schemeRegistration = entry.getKey();
      String existingLauncher = existingRegistrations.get(schemeRegistration);
      String newLauncher = entry.getValue();
      if (!newLauncher.equals(existingLauncher))
      {
        for (IScheme scheme : SCHEMES)
        {
          if (scheme.getName().equals(schemeRegistration))
          {
            try
            {
              if (OS.INSTANCE.isMac())
              {
                // The Mac implementation refuses unregister a conflicting registration so force it.
                Runnable restore = setEclipseHome(existingLauncher);
                try
                {
                  OPERATING_SYSTEM_REGISTRATION.handleSchemes(Collections.<IScheme> emptyList(), Collections.singleton(scheme));
                }
                catch (Exception ex)
                {
                  SetupInstallerPlugin.INSTANCE.log(ex);
                }
                finally
                {
                  if (restore != null)
                  {
                    restore.run();
                  }
                }
              }
              else
              {
                OPERATING_SYSTEM_REGISTRATION.handleSchemes(Collections.<IScheme> emptyList(), Collections.singleton(scheme));
              }

              if (!StringUtil.isEmpty(newLauncher))
              {
                Runnable restore = setEclipseHome(FAKE_ECLIPSE_HOME);
                OPERATING_SYSTEM_REGISTRATION.handleSchemes(Collections.singleton(scheme), Collections.<IScheme> emptyList());
                if (restore != null)
                {
                  restore.run();
                }
              }
            }
            catch (Exception ex)
            {
              SetupInstallerPlugin.INSTANCE.log(ex);
            }

            break;
          }
        }
      }
    }
  }

  /**
   * Registers or unregisters this installer's registrations and remembers this state in the web link preference.
   */
  public static void setRegistered(boolean registered)
  {
    String eclipseLauncher = getSelfLauncher();
    if (!StringUtil.isEmpty(eclipseLauncher))
    {
      try
      {
        if (!registered)
        {
          Set<String> selfRegistrations = getSelfRegistrations();
          for (IScheme scheme : SCHEMES)
          {
            if (selfRegistrations.contains(scheme.getName()))
            {
              OPERATING_SYSTEM_REGISTRATION.handleSchemes(Collections.<IScheme> emptyList(), Collections.singleton(scheme));
            }
          }
        }

        if (registered)
        {
          OPERATING_SYSTEM_REGISTRATION.handleSchemes(SCHEMES, Collections.<IScheme> emptyList());
        }

        PREF_WEB_LINKS.set(registered);
      }
      catch (Exception ex)
      {
        SetupInstallerPlugin.INSTANCE.log(ex);
      }
    }
  }

  /**
   * The result of a registration confirmation.
   */
  enum RegistrationConfirmation
  {
    /**
     * The installer should be kept before registration is possible.
     */
    KEEP_INSTALLER,
    /**
     * It's okay to do the registration.
     */
    OK,
    /**
     * The registration is canceled.
     */
    CANCEL,
    /**
     * The registration has already been completed.
     */
    DONE
  }

  /**
   * Prompts for saving the installer to a permanent location if it is transient returning that result.
   * Otherwise prompts for the choices of which schemes to register, returning that result.
   */
  public static RegistrationConfirmation manageRegistrations(Shell shell)
  {
    if (KeepInstallerUtil.isTransientInstaller())
    {
      if (MessageDialog.openConfirm(shell, Messages.URISchemeUtil_title, Messages.URISchemeUtil_description))
      {
        return RegistrationConfirmation.KEEP_INSTALLER;
      }

      return RegistrationConfirmation.CANCEL;
    }

    URISchemeDialog uriSchemeDialog = new URISchemeDialog(shell);
    if (uriSchemeDialog.open() == Window.CANCEL)
    {
      return RegistrationConfirmation.CANCEL;
    }

    return RegistrationConfirmation.DONE;
  }

  /**
   * Used when enabling registration via the toggle button in simple mode.
   * Prompts for saving the installer to a permanent location if it is transient returning that result.
   * Otherwise, if there are conflicting registrations,
   * prompts for the choices of which schemes to register, returning that result.
   * Otherwise returns OK, i.e., that it's okay to call setRegistered(true) in order to register this installer.
   */
  public static RegistrationConfirmation confirmRegistration(Shell shell)
  {
    if (KeepInstallerUtil.isTransientInstaller())
    {
      if (MessageDialog.openConfirm(shell, Messages.URISchemeUtil_title, Messages.URISchemeUtil_description))
      {
        return RegistrationConfirmation.KEEP_INSTALLER;
      }

      return RegistrationConfirmation.CANCEL;
    }

    Map<String, String> conflictingRegistrations = URISchemeUtil.getConflictingRegistrations();
    if (!conflictingRegistrations.isEmpty())
    {
      URISchemeDialog uriSchemeDialog = new URISchemeDialog(shell);
      if (uriSchemeDialog.open() == Window.CANCEL)
      {
        return RegistrationConfirmation.CANCEL;
      }

      return RegistrationConfirmation.DONE;
    }

    return RegistrationConfirmation.OK;
  }

  /**
   * Returns a map from web link schemes to the current conflicting launcher for that scheme.
   */
  public static Map<String, String> getConflictingRegistrations()
  {
    Map<String, String> result = new LinkedHashMap<>();
    try
    {
      List<ISchemeInformation> schemesInformation = OPERATING_SYSTEM_REGISTRATION.getSchemesInformation(SCHEMES);
      String eclipseLauncher = getSelfLauncher();
      for (ISchemeInformation schemeInformation : schemesInformation)
      {
        String handlerInstanceLocation = schemeInformation.getHandlerInstanceLocation();
        if (!StringUtil.isEmpty(handlerInstanceLocation) && !handlerInstanceLocation.equals(eclipseLauncher))
        {
          result.put(schemeInformation.getName(), handlerInstanceLocation);
        }
      }
    }
    catch (Exception ex)
    {
    }

    return result;
  }

  /**
   * Returns the web link schemes currently registered for this installer.
   */
  public static Set<String> getSelfRegistrations()
  {
    Set<String> result = new LinkedHashSet<>();
    String eclipseLauncher = getSelfLauncher();
    if (!StringUtil.isEmpty(eclipseLauncher))
    {
      try
      {
        List<ISchemeInformation> schemesInformation = OPERATING_SYSTEM_REGISTRATION.getSchemesInformation(SCHEMES);
        for (ISchemeInformation schemeInformation : schemesInformation)
        {
          String handlerInstanceLocation = schemeInformation.getHandlerInstanceLocation();
          if (eclipseLauncher.equals(handlerInstanceLocation))
          {
            result.add(schemeInformation.getName());
          }
        }
      }
      catch (Exception ex)
      {
      }
    }

    return result;
  }

  /**
   * Returns a map from web link scheme to the currently registered launcher for that scheme.
   */
  public static Map<String, String> getRegistrations()
  {
    Map<String, String> result = new LinkedHashMap<>();
    try
    {
      List<ISchemeInformation> schemesInformation = OPERATING_SYSTEM_REGISTRATION.getSchemesInformation(SCHEMES);
      for (ISchemeInformation schemeInformation : schemesInformation)
      {
        String handlerInstanceLocation = schemeInformation.getHandlerInstanceLocation();
        result.put(schemeInformation.getName(), handlerInstanceLocation);
      }
    }
    catch (Exception ex)
    {
    }

    return result;
  }
}
