/*
 * Copyright (c) 2014, 2016 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.p2.internal.core;

import org.eclipse.oomph.util.CollectionUtil;
import org.eclipse.oomph.util.IOUtil;
import org.eclipse.oomph.util.StringUtil;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectInputStream;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.equinox.p2.metadata.Version;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @author Eike Stepper
 */
public class P2IndexImpl implements P2Index
{
  public static final P2IndexImpl INSTANCE = new P2IndexImpl();

  private static final String INDEX_BASE = "http://download.eclipse.org/oomph/index/";

  private long timeStamp;

  private Map<Integer, RepositoryImpl> repositories;

  private Repository[] repositoriesArray;

  private Map<String, Set<String>> capabilitiesMap;

  private File repositoriesCacheFile;

  private File capabilitiesCacheFile;

  private P2IndexImpl()
  {
  }

  private synchronized void initCapabilities()
  {
    if (capabilitiesMap == null)
    {
      capabilitiesMap = new LinkedHashMap<String, Set<String>>();

      ZipFile zipFile = null;
      InputStream inputStream = null;

      try
      {
        boolean refreshed = initCapabilitiesCacheFile();

        zipFile = new ZipFile(capabilitiesCacheFile);
        ZipEntry zipEntry = zipFile.getEntry("capabilities");

        inputStream = zipFile.getInputStream(zipEntry);

        Map<Object, Object> options = new HashMap<Object, Object>();
        options.put(BinaryResourceImpl.OPTION_VERSION, BinaryResourceImpl.BinaryIO.Version.VERSION_1_1);
        options.put(BinaryResourceImpl.OPTION_STYLE_DATA_CONVERTER, Boolean.TRUE);
        options.put(BinaryResourceImpl.OPTION_BUFFER_CAPACITY, 8192);

        EObjectInputStream stream = new BinaryResourceImpl.EObjectInputStream(inputStream, options);
        int refreshHours = stream.readInt();
        int mapSize = stream.readCompressedInt();
        for (int i = 0; i < mapSize; ++i)
        {
          String key = stream.readSegmentedString();
          int valuesSize = stream.readCompressedInt();
          for (int j = 0; j < valuesSize; ++j)
          {
            String value = stream.readSegmentedString();
            CollectionUtil.add(capabilitiesMap, key, value);
          }
        }

        if (refreshed)
        {
          File validityFile = getCapabilitiesValidityFile();
          IOUtil.writeLines(validityFile, "UTF-8", Collections.singletonList("" + Long.toString(System.currentTimeMillis() + refreshHours * 60 * 60 * 1000)));
        }
      }
      catch (Exception ex)
      {
        P2CorePlugin.INSTANCE.log(ex, IStatus.WARNING);
      }
      finally
      {
        IOUtil.closeSilent(inputStream);
        if (zipFile != null)
        {
          try
          {
            zipFile.close();
          }
          catch (IOException ex)
          {
            P2CorePlugin.INSTANCE.log(ex, IStatus.WARNING);
          }
        }
      }
    }
  }

  private synchronized void initRepositories(boolean force)
  {
    if (repositories == null || force)
    {
      repositories = new HashMap<Integer, RepositoryImpl>();

      ZipFile zipFile = null;
      InputStream inputStream = null;

      try
      {
        boolean refreshed = initRepositoriesCacheFile();

        zipFile = new ZipFile(repositoriesCacheFile);
        ZipEntry zipEntry = zipFile.getEntry("repositories");

        inputStream = zipFile.getInputStream(zipEntry);

        Map<Object, Object> options = new HashMap<Object, Object>();
        options.put(BinaryResourceImpl.OPTION_VERSION, BinaryResourceImpl.BinaryIO.Version.VERSION_1_1);
        options.put(BinaryResourceImpl.OPTION_STYLE_DATA_CONVERTER, Boolean.TRUE);
        options.put(BinaryResourceImpl.OPTION_BUFFER_CAPACITY, 8192);

        EObjectInputStream stream = new BinaryResourceImpl.EObjectInputStream(inputStream, options);

        timeStamp = stream.readLong();
        int refreshHours = stream.readInt();
        int repositoryCount = stream.readInt();

        if (refreshed)
        {
          File validityFile = getRepositoriesValidityFile();
          IOUtil.writeLines(validityFile, "UTF-8", Collections.singletonList("" + Long.toString(System.currentTimeMillis() + refreshHours * 60 * 60 * 1000)));
        }

        Map<RepositoryImpl, List<Integer>> composedRepositories = new HashMap<RepositoryImpl, List<Integer>>();
        for (int id = 1; id <= repositoryCount; id++)
        {
          RepositoryImpl repository = new RepositoryImpl(stream, id, composedRepositories);
          repositories.put(id, repository);
        }

        for (Map.Entry<RepositoryImpl, List<Integer>> entry : composedRepositories.entrySet())
        {
          RepositoryImpl repository = entry.getKey();
          for (int compositeID : entry.getValue())
          {
            RepositoryImpl composite = repositories.get(compositeID);
            if (composite != null)
            {
              composite.addChild(repository);
              repository.addComposite(composite);
            }
          }
        }

        repositoriesArray = repositories.values().toArray(new Repository[repositories.size()]);
      }
      catch (Exception ex)
      {
        P2CorePlugin.INSTANCE.log(ex, IStatus.WARNING);
      }
      finally
      {
        IOUtil.close(inputStream);
        if (zipFile != null)
        {
          try
          {
            zipFile.close();
          }
          catch (IOException ex)
          {
            P2CorePlugin.INSTANCE.log(ex, IStatus.WARNING);
          }
        }
      }
    }
  }

  private boolean initRepositoriesCacheFile() throws Exception
  {
    if (repositoriesCacheFile == null)
    {
      IPath stateLocation = P2CorePlugin.INSTANCE.isOSGiRunning() ? P2CorePlugin.INSTANCE.getStateLocation() : new Path(".");
      repositoriesCacheFile = new File(stateLocation.toOSString(), "repositories");
    }

    if (repositoriesCacheFile.exists())
    {
      File validityFile = getRepositoriesValidityFile();
      List<String> lines = IOUtil.readLines(validityFile, "UTF-8");
      long validUntil = Long.parseLong(lines.get(0));
      if (System.currentTimeMillis() <= validUntil)
      {
        return false;
      }
    }

    InputStream inputStream = null;
    OutputStream outputStream = null;

    try
    {
      inputStream = new URL(INDEX_BASE + "repositories").openStream();
      outputStream = new FileOutputStream(repositoriesCacheFile);
      IOUtil.copy(inputStream, outputStream);
    }
    finally
    {
      IOUtil.close(outputStream);
      IOUtil.close(inputStream);
    }

    return true;
  }

  private boolean initCapabilitiesCacheFile() throws Exception
  {
    if (capabilitiesCacheFile == null)
    {
      IPath stateLocation = P2CorePlugin.INSTANCE.isOSGiRunning() ? P2CorePlugin.INSTANCE.getStateLocation() : new Path(".");
      capabilitiesCacheFile = new File(stateLocation.toOSString(), "capabilities");
    }

    if (capabilitiesCacheFile.exists())
    {
      File validityFile = getCapabilitiesValidityFile();
      List<String> lines = IOUtil.readLines(validityFile, "UTF-8");
      long validUntil = Long.parseLong(lines.get(0));
      if (System.currentTimeMillis() <= validUntil)
      {
        return false;
      }
    }

    InputStream inputStream = null;
    OutputStream outputStream = null;

    try
    {
      inputStream = new URL(INDEX_BASE + "capabilities").openStream();
      outputStream = new FileOutputStream(capabilitiesCacheFile);
      IOUtil.copy(inputStream, outputStream);
    }
    finally
    {
      IOUtil.close(outputStream);
      IOUtil.close(inputStream);
    }

    return true;
  }

  private File getRepositoriesValidityFile()
  {
    return new File(repositoriesCacheFile.getParentFile(), "repositories.txt");
  }

  private File getCapabilitiesValidityFile()
  {
    return new File(capabilitiesCacheFile.getParentFile(), "capabilities.txt");
  }

  public Repository[] getRepositories()
  {
    initRepositories(false);
    return repositoriesArray;
  }

  public Map<String, Set<String>> getCapabilities()
  {
    initCapabilities();
    return Collections.unmodifiableMap(capabilitiesMap);
  }

  public Map<Repository, Set<Version>> lookupCapabilities(String namespace, String name)
  {
    Map<Repository, Set<Version>> capabilities = new HashMap<Repository, Set<Version>>();
    if (!StringUtil.isEmpty(namespace) && !StringUtil.isEmpty(name))
    {
      namespace = URI.encodeSegment(namespace, false);
      name = URI.encodeSegment(name, false);

      BufferedReader reader = null;

      try
      {
        InputStream inputStream = new URL(INDEX_BASE + namespace + "/" + name).openStream();
        reader = new BufferedReader(new InputStreamReader(inputStream));

        String line = reader.readLine();
        if (line == null)
        {
          return capabilities;
        }

        long timeStamp = Long.parseLong(line);
        initRepositories(timeStamp != this.timeStamp);

        while ((line = reader.readLine()) != null)
        {
          String[] tokens = line.split(",");
          int repositoryID = Integer.parseInt(tokens[0]);
          Repository repository = repositories.get(repositoryID);
          if (repository != null)
          {
            Set<Version> versions = new HashSet<Version>();
            for (int i = 1; i < tokens.length; i++)
            {
              versions.add(Version.parseVersion(tokens[i]));
            }

            capabilities.put(repository, versions);
          }
        }
      }
      catch (FileNotFoundException ex)
      {
        // Ignore.
      }
      catch (Exception ex)
      {
        P2CorePlugin.INSTANCE.log(ex, IStatus.WARNING);
      }
      finally
      {
        IOUtil.close(reader);
      }
    }

    return capabilities;
  }

  public Map<Repository, Set<Version>> generateCapabilitiesFromComposedRepositories(Map<Repository, Set<Version>> capabilitiesFromSimpleRepositories)
  {
    Map<Repository, Set<Version>> capabilities = new HashMap<Repository, Set<Version>>();
    for (Map.Entry<Repository, Set<Version>> entry : capabilitiesFromSimpleRepositories.entrySet())
    {
      Repository repository = entry.getKey();
      Set<Version> versions = entry.getValue();
      recurseComposedRepositories(capabilities, repository, versions);
    }

    return capabilities;
  }

  private void recurseComposedRepositories(Map<Repository, Set<Version>> capabilities, Repository repository, Set<Version> versions)
  {
    for (Repository composite : repository.getComposites())
    {
      Set<Version> set = capabilities.get(composite);
      if (set == null)
      {
        set = new HashSet<Version>();
        capabilities.put(composite, set);
      }

      set.addAll(versions);
      recurseComposedRepositories(capabilities, composite, versions);
    }
  }

  /**
   * @author Eike Stepper
   */
  public static final class RepositoryImpl implements Repository
  {
    public static final int UNINITIALIZED = -1;

    private static final Repository[] NO_REPOSITORIES = {};

    private final URI location;

    private final int id;

    private final boolean composed;

    private final boolean compressed;

    private final long timestamp;

    private int capabilityCount;

    private Repository[] children;

    private Repository[] composites;

    public RepositoryImpl(EObjectInputStream stream, int id, Map<RepositoryImpl, List<Integer>> composedRepositories) throws IOException
    {
      this.id = id;
      location = stream.readURI();
      composed = stream.readBoolean();
      compressed = stream.readBoolean();
      timestamp = stream.readLong();

      if (composed)
      {
        capabilityCount = UNINITIALIZED;
      }
      else
      {
        capabilityCount = stream.readInt();
      }

      List<Integer> composites = null;
      while (stream.readBoolean())
      {
        if (composites == null)
        {
          composites = new ArrayList<Integer>();
          composedRepositories.put(this, composites);
        }

        int composite = stream.readInt();
        composites.add(composite);
      }
    }

    public URI getLocation()
    {
      return location;
    }

    public int getID()
    {
      return id;
    }

    public boolean isComposed()
    {
      return composed;
    }

    public boolean isCompressed()
    {
      return compressed;
    }

    public long getTimestamp()
    {
      return timestamp;
    }

    public int getCapabilityCount()
    {
      if (composed && capabilityCount == UNINITIALIZED)
      {
        capabilityCount = 0;
        for (Repository child : getChildren())
        {
          capabilityCount += child.getCapabilityCount();
        }
      }

      return capabilityCount;
    }

    public Repository[] getChildren()
    {
      if (children == null)
      {
        return NO_REPOSITORIES;
      }

      return children;
    }

    public Repository[] getComposites()
    {
      if (composites == null)
      {
        return NO_REPOSITORIES;
      }

      return composites;
    }

    @Override
    public int hashCode()
    {
      final int prime = 31;
      int result = 1;
      result = prime * result + id;
      return result;
    }

    @Override
    public boolean equals(Object obj)
    {
      if (this == obj)
      {
        return true;
      }

      if (obj == null)
      {
        return false;
      }

      if (getClass() != obj.getClass())
      {
        return false;
      }

      RepositoryImpl other = (RepositoryImpl)obj;
      if (id != other.id)
      {
        return false;
      }

      return true;
    }

    public int compareTo(Repository o)
    {
      return location.toString().compareTo(o.getLocation().toString());
    }

    @Override
    public String toString()
    {
      return location.toString();
    }

    public void addChild(Repository child)
    {
      children = addRepository(children, child);
    }

    public void addComposite(Repository composite)
    {
      composites = addRepository(composites, composite);
    }

    private Repository[] addRepository(Repository[] repositories, Repository repository)
    {
      if (repositories == null)
      {
        return new Repository[] { repository };
      }

      int length = repositories.length;
      Repository[] newRepositories = new Repository[length + 1];
      System.arraycopy(repositories, 0, newRepositories, 0, length);
      newRepositories[length] = repository;
      return newRepositories;
    }
  }
}
