/*
 * Copyright (c) 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.userstorage.internal;

import org.eclipse.userstorage.IStorageService;
import org.eclipse.userstorage.internal.StorageService.DynamicService;
import org.eclipse.userstorage.internal.util.StringUtil;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IRegistryEventListener;
import org.eclipse.core.runtime.Platform;
import org.eclipse.equinox.security.storage.ISecurePreferences;
import org.eclipse.equinox.security.storage.StorageException;

import java.lang.ref.WeakReference;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author Eike Stepper
 */
public final class StorageServiceRegistry implements IStorageService.Registry
{
  public static final StorageServiceRegistry INSTANCE = new StorageServiceRegistry();

  private static final ExtensionPointHandler HANDLER = new ExtensionPointHandler();

  private static final String PREFIX = "org.eclipse.userstorage.";

  private static final String SERVICE_LABEL = "serviceLabel";

  private static final String SERVICE_URI = "serviceURI";

  private static final String CREATE_ACCOUNT_URI = "createAccountURI";

  private static final String EDIT_ACCOUNT_URI = "editAccountURI";

  private static final String RECOVER_PASSWORD_URI = "recoverPasswordURI";

  private static final String TERMS_OF_USE_LINK = "termsOfUseLink";

  private static final String DEFAULT_SERVICE_LABEL = "Eclipse.org";

  private static final String DEFAULT_SERVICE_URI = "https://api.eclipse.org/";

  private static final String STAGING_SERVICE_URI = "https://api-staging.eclipse.org/";

  private final List<Listener> listeners = new CopyOnWriteArrayList<Listener>();

  private final Set<WeakReference<Storage>> storages = new HashSet<WeakReference<Storage>>();

  private final Map<URI, IStorageService> services = new LinkedHashMap<URI, IStorageService>();

  private boolean running;

  private StorageServiceRegistry()
  {
  }

  @Override
  public IStorageService[] getServices()
  {
    synchronized (services)
    {
      start();
      return services.values().toArray(new IStorageService[services.size()]);
    }
  }

  @Override
  public StorageService getService(URI serviceURI)
  {
    synchronized (services)
    {
      start();
      return (StorageService)services.get(serviceURI);
    }
  }

  public StorageService getFirstService()
  {
    synchronized (services)
    {
      start();

      if (services.isEmpty())
      {
        return null;
      }

      return (StorageService)services.values().iterator().next();
    }
  }

  @Override
  public IStorageService.Dynamic addService(String serviceLabel, URI serviceURI, URI createAccountURI, URI editAccountURI, URI recoverPasswordURI,
      String termsOfUseLink) throws IllegalStateException
  {
    DynamicService service = new DynamicService(serviceLabel, serviceURI, createAccountURI, editAccountURI, recoverPasswordURI, termsOfUseLink);
    addService(service);

    ISecurePreferences securePreferences = service.getSecurePreferences();
    if (securePreferences != null)
    {
      try
      {
        securePreferences.put(SERVICE_LABEL, serviceLabel, false);
        securePreferences.put(SERVICE_URI, serviceURI.toString(), false);
        setSecurePreference(securePreferences, CREATE_ACCOUNT_URI, createAccountURI);
        setSecurePreference(securePreferences, EDIT_ACCOUNT_URI, editAccountURI);
        setSecurePreference(securePreferences, RECOVER_PASSWORD_URI, recoverPasswordURI);
        securePreferences.flush();
      }
      catch (Exception ex)
      {
        Activator.log(ex);
      }
    }

    return service;
  }

  @Override
  public IStorageService.Dynamic addService(String serviceLabel, URI serviceURI) throws IllegalStateException
  {
    return addService(serviceLabel, serviceURI, null, null, null, null);
  }

  @Override
  public IStorageService.Dynamic[] refresh()
  {
    List<IStorageService.Dynamic> result = new ArrayList<IStorageService.Dynamic>();

    ISecurePreferences securePreferences = Activator.getSecurePreferences();
    if (securePreferences != null)
    {
      for (String name : securePreferences.childrenNames())
      {
        try
        {
          ISecurePreferences child = securePreferences.node(name);

          String serviceLabel = child.get(SERVICE_LABEL, null);
          if (StringUtil.isEmpty(serviceLabel))
          {
            continue;
          }

          URI serviceURI = StringUtil.newURI(child.get(SERVICE_URI, null));
          if (serviceURI == null || !StringUtil.encodeURI(serviceURI).equals(name))
          {
            continue;
          }

          URI createAccountURI = StringUtil.newURI(child.get(CREATE_ACCOUNT_URI, null));
          URI editAccountURI = StringUtil.newURI(child.get(EDIT_ACCOUNT_URI, null));
          URI recoverPasswordURI = StringUtil.newURI(child.get(RECOVER_PASSWORD_URI, null));
          String termsOfUseLink = child.get(TERMS_OF_USE_LINK, null);

          IStorageService.Dynamic service = new DynamicService(serviceLabel, serviceURI, createAccountURI, editAccountURI, recoverPasswordURI, termsOfUseLink);
          addService(service);
          result.add(service);
        }
        catch (Exception ex)
        {
          //$FALL-THROUGH$
        }
      }
    }

    return result.toArray(new IStorageService.Dynamic[result.size()]);
  }

  @Override
  public void addListener(Listener listener)
  {
    listeners.add(listener);
  }

  @Override
  public void removeListener(Listener listener)
  {
    listeners.remove(listener);
  }

  void addStorage(Storage storage)
  {
    synchronized (storages)
    {
      storages.add(new WeakReference<Storage>(storage));
    }
  }

  void addService(IStorageService service) throws IllegalStateException
  {
    URI serviceURI = service.getServiceURI();

    synchronized (services)
    {
      start();

      IStorageService registered = services.get(serviceURI);
      if (registered != null)
      {
        throw new IllegalStateException("Service already registered: " + registered);
      }

      services.put(serviceURI, service);
    }

    for (Listener listener : listeners)
    {
      try
      {
        listener.serviceAdded(service);
      }
      catch (Exception ex)
      {
        Activator.log(ex);
      }
    }
  }

  void removeService(IStorageService service)
  {
    URI serviceURI = service.getServiceURI();

    synchronized (services)
    {
      start();
      services.remove(serviceURI);
    }

    for (Listener listener : listeners)
    {
      try
      {
        listener.serviceRemoved(service);
      }
      catch (Exception ex)
      {
        Activator.log(ex);
      }
    }

    List<Storage> storagesToNotify = new ArrayList<Storage>();
    synchronized (storages)
    {
      for (Iterator<WeakReference<Storage>> it = storages.iterator(); it.hasNext();)
      {
        WeakReference<Storage> ref = it.next();
        Storage storage = ref.get();
        if (storage != null)
        {
          storagesToNotify.add(storage);
        }
        else
        {
          it.remove();
        }
      }
    }

    for (Storage storage : storagesToNotify)
    {
      storage.serviceRemoved(service);
    }
  }

  void start()
  {
    synchronized (services)
    {
      if (!running)
      {
        running = true;

        try
        {
          URI serviceURI = StringUtil.newURI(System.getProperty(PREFIX + SERVICE_URI, null));
          if (serviceURI == null)
          {
            if (Boolean.getBoolean(PREFIX + "staging"))
            {
              serviceURI = StringUtil.newURI(STAGING_SERVICE_URI);
            }
            else
            {
              serviceURI = StringUtil.newURI(DEFAULT_SERVICE_URI);
            }
          }

          if (serviceURI != null)
          {
            String serviceLabel = System.getProperty(PREFIX + SERVICE_LABEL, DEFAULT_SERVICE_LABEL);
            URI createAccountURI = StringUtil.newURI(getValue(serviceURI, CREATE_ACCOUNT_URI, "https://dev.eclipse.org/site_login/"));
            URI editAccountURI = StringUtil.newURI(getValue(serviceURI, EDIT_ACCOUNT_URI, "https://dev.eclipse.org/site_login/myaccount.php"));
            URI recoverPasswordURI = StringUtil.newURI(getValue(serviceURI, RECOVER_PASSWORD_URI, "https://dev.eclipse.org/site_login/password_recovery.php"));
            String termsOfUseLink = getValue(serviceURI, TERMS_OF_USE_LINK,
                "I agree the use of this beta service is governed by the Eclipse Foundation <a href='http://www.eclipse.org/legal/termsofuse.php'>Terms of Use</a> and the Eclipse Foundation <a href='http://www.eclipse.org/legal/privacy.php'>Privacy Policy</a>.");

            StorageService eclipseStorage = new StorageService(serviceLabel, serviceURI, createAccountURI, editAccountURI, recoverPasswordURI, termsOfUseLink);
            services.put(eclipseStorage.getServiceURI(), eclipseStorage);
          }

          if (Activator.PLATFORM_RUNNING)
          {
            HANDLER.start();
          }

          refresh();
        }
        catch (Exception ex)
        {
          Activator.log(ex);
        }
      }
    }
  }

  void stop() throws Exception
  {
    synchronized (services)
    {
      if (running)
      {
        running = false;

        try
        {
          if (Activator.PLATFORM_RUNNING)
          {
            HANDLER.stop();
          }

          services.clear();
        }
        catch (Exception ex)
        {
          Activator.log(ex);
        }
      }
    }
  }

  private static String getValue(URI serviceURI, String property, String defaultValue)
  {
    String value = System.getProperty(PREFIX + property);
    if (StringUtil.isEmpty(value))
    {
      String authority = serviceURI.getAuthority();
      if (authority != null && authority.endsWith(".eclipse.org"))
      {
        value = defaultValue;
      }
    }

    return value;
  }

  private static void setSecurePreference(ISecurePreferences securePreferences, String key, URI uri) throws StorageException
  {
    if (uri != null)
    {
      securePreferences.put(key, uri.toString(), false);
    }
    else
    {
      securePreferences.remove(key);
    }
  }

  /**
   * @author Eike Stepper
   */
  private static final class ExtensionPointHandler implements IRegistryEventListener
  {
    private static final String EXTENSION_POINT = Activator.PLUGIN_ID + ".storages";

    public ExtensionPointHandler()
    {
    }

    public void start() throws Exception
    {
      IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
      for (IConfigurationElement configurationElement : extensionRegistry.getConfigurationElementsFor(EXTENSION_POINT))
      {
        added(configurationElement);
      }

      extensionRegistry.addListener(this, EXTENSION_POINT);
    }

    public void stop() throws Exception
    {
      Platform.getExtensionRegistry().removeListener(this);
    }

    @Override
    public void added(IExtensionPoint[] extensionPoints)
    {
      // Do nothing
    }

    @Override
    public void removed(IExtensionPoint[] extensionPoints)
    {
      // Do nothing
    }

    @Override
    public void added(IExtension[] extensions)
    {
      for (IExtension extension : extensions)
      {
        for (IConfigurationElement configurationElement : extension.getConfigurationElements())
        {
          added(configurationElement);
        }
      }
    }

    @Override
    public void removed(IExtension[] extensions)
    {
      for (IExtension extension : extensions)
      {
        for (IConfigurationElement configurationElement : extension.getConfigurationElements())
        {
          removed(configurationElement);
        }
      }
    }

    private void added(IConfigurationElement configurationElement)
    {
      try
      {
        StorageService storage = createStorage(configurationElement);
        INSTANCE.addService(storage);
      }
      catch (Exception ex)
      {
        Activator.log(ex);
      }
    }

    private void removed(IConfigurationElement configurationElement)
    {
      try
      {
        StorageService storage = createStorage(configurationElement);
        INSTANCE.removeService(storage);
      }
      catch (Exception ex)
      {
        Activator.log(ex);
      }
    }

    private StorageService createStorage(IConfigurationElement configurationElement)
    {
      String serviceLabel = configurationElement.getAttribute(SERVICE_LABEL);
      URI serviceURI = StringUtil.newURI(configurationElement.getAttribute(SERVICE_URI));
      URI createAccountURI = StringUtil.newURI(configurationElement.getAttribute(CREATE_ACCOUNT_URI));
      URI editAccountURI = StringUtil.newURI(configurationElement.getAttribute(EDIT_ACCOUNT_URI));
      URI recoverPasswordURI = StringUtil.newURI(configurationElement.getAttribute(RECOVER_PASSWORD_URI));
      String termsOfUseLink = configurationElement.getAttribute(TERMS_OF_USE_LINK);

      return new StorageService(serviceLabel, serviceURI, createAccountURI, editAccountURI, recoverPasswordURI, termsOfUseLink);
    }
  }
}
