// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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.gitiles;

import com.google.common.base.Enums;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import org.eclipse.jgit.api.ArchiveCommand;
import org.eclipse.jgit.archive.TarFormat;
import org.eclipse.jgit.archive.Tbz2Format;
import org.eclipse.jgit.archive.TgzFormat;
import org.eclipse.jgit.archive.TxzFormat;
import org.eclipse.jgit.lib.Config;

public enum ArchiveFormat {
  TGZ("application/x-gzip", new TgzFormat()),
  TAR("application/x-tar", new TarFormat()),
  TBZ2("application/x-bzip2", new Tbz2Format()),
  TXZ("application/x-xz", new TxzFormat());
  // Zip is not supported because it may be interpreted by a Java plugin as a
  // valid JAR file, whose code would have access to cookies on the domain.

  private static final ImmutableMap<String, ArchiveFormat> BY_EXT;
  static {
    ImmutableMap.Builder<String, ArchiveFormat> byExt = ImmutableMap.builder();
    for (ArchiveFormat format : ArchiveFormat.values()) {
      for (String ext : format.getSuffixes()) {
        byExt.put(ext.toLowerCase(), format);
      }
    }
    BY_EXT = byExt.build();
  }

  /** Unregister all JGit archive formats supported by Gitiles. */
  public static void unregisterAll() {
    for (ArchiveFormat fmt : values()) {
      ArchiveCommand.unregisterFormat(fmt.getRegisteredName());
    }
  }

  private final ArchiveCommand.Format<?> format;
  private final String mimeType;

  private ArchiveFormat(String mimeType, ArchiveCommand.Format<?> format) {
    this.format = format;
    this.mimeType = mimeType;
    ArchiveCommand.registerFormat(getRegisteredName(), format);
  }

  String getRegisteredName() {
    return getShortName();
  }

  String getShortName() {
    return name().toLowerCase();
  }

  String getMimeType() {
    return mimeType;
  }

  String getDefaultSuffix() {
    return getSuffixes().iterator().next();
  }

  Iterable<String> getSuffixes() {
    return format.suffixes();
  }

  static ArchiveFormat getDefault(Config cfg) {
    for (String allowed : cfg.getStringList("archive", null, "format")) {
      Optional<ArchiveFormat> result =
          Enums.getIfPresent(ArchiveFormat.class, allowed.toUpperCase());
      if (result.isPresent()) {
        return result.get();
      }
    }
    return TGZ;
  }

  static ImmutableSet<String> allExtensions() {
    return BY_EXT.keySet();
  }

  static Optional<ArchiveFormat> byExtension(String ext, Config cfg) {
    ArchiveFormat format = BY_EXT.get(ext);
    if (format == null) {
      return Optional.absent();
    }
    String[] formats = cfg.getStringList("archive", null, "format");
    if (formats.length == 0) {
      return Optional.of(format);
    }
    for (String allowed : formats) {
      if (format.name().equals(allowed.toUpperCase())) {
        return Optional.of(format);
      }
    }
    return Optional.absent();
  }
}
