// Copyright (C) 2010 The Android Open Source Project
//
// 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.gerrit.server.tools;

import com.google.gerrit.common.Version;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Listing of all client side tools stored on this server.
 * <p>
 * Clients may download these tools through our file server, as they are
 * packaged with our own software releases.
 */
@Singleton
public class ToolsCatalog {
  private static final Logger log = LoggerFactory.getLogger(ToolsCatalog.class);

  private final SortedMap<String, Entry> toc;

  @Inject
  ToolsCatalog() throws IOException {
    this.toc = readToc();
  }

  /**
   * Lookup an entry in the tools catalog.
   *
   * @param name path of the item, relative to the root of the catalog.
   * @return the entry; null if the item is not part of the catalog.
   */
  public Entry get(String name) {
    if (name.startsWith("/")) {
      name = name.substring(1);
    }
    if (name.endsWith("/")) {
      name = name.substring(0, name.length() - 1);
    }
    return toc.get(name);
  }

  private static SortedMap<String, Entry> readToc() throws IOException {
    SortedMap<String, Entry> toc = new TreeMap<String, Entry>();
    final BufferedReader br =
        new BufferedReader(new InputStreamReader(new ByteArrayInputStream(
            read("TOC")), "UTF-8"));
    String line;
    while ((line = br.readLine()) != null) {
      if (line.length() > 0 && !line.startsWith("#")) {
        final Entry e = new Entry(Entry.Type.FILE, line);
        toc.put(e.getPath(), e);
      }
    }

    final List<Entry> all = new ArrayList<Entry>(toc.values());
    for (Entry e : all) {
      String path = dirOf(e.getPath());
      while (path != null) {
        Entry d = toc.get(path);
        if (d == null) {
          d = new Entry(Entry.Type.DIR, 0755, path);
          toc.put(d.getPath(), d);
        }
        d.children.add(e);
        path = dirOf(path);
        e = d;
      }
    }

    final Entry top = new Entry(Entry.Type.DIR, 0755, "");
    for (Entry e : toc.values()) {
      if (dirOf(e.getPath()) == null) {
        top.children.add(e);
      }
    }
    toc.put(top.getPath(), top);

    return Collections.unmodifiableSortedMap(toc);
  }

  private static byte[] read(String path) {
    String name = "root/" + path;
    InputStream in = ToolsCatalog.class.getResourceAsStream(name);
    if (in == null) {
      return null;
    }

    try {
      final ByteArrayOutputStream out = new ByteArrayOutputStream();
      try {
        final byte[] buf = new byte[8192];
        int n;
        while ((n = in.read(buf, 0, buf.length)) > 0) {
          out.write(buf, 0, n);
        }
      } finally {
        in.close();
      }
      return out.toByteArray();
    } catch (Exception e) {
      log.debug("Cannot read " + path, e);
      return null;
    }
  }

  private static String dirOf(String path) {
    final int s = path.lastIndexOf('/');
    return s < 0 ? null : path.substring(0, s);
  }

  /** A file served out of the tools root directory. */
  public static class Entry {
    public static enum Type {
      DIR, FILE;
    }

    private final Type type;
    private final int mode;
    private final String path;
    private final List<Entry> children;

    Entry(Type type, String line) {
      int s = line.indexOf(' ');
      String mode = line.substring(0, s);
      String path = line.substring(s + 1);

      this.type = type;
      this.mode = Integer.parseInt(mode, 8);
      this.path = path;
      if (type == Type.FILE) {
        this.children = Collections.emptyList();
      } else {
        this.children = new ArrayList<Entry>();
      }
    }

    Entry(Type type, int mode, String path) {
      this.type = type;
      this.mode = mode;
      this.path = path;
      this.children = new ArrayList<Entry>();
    }

    public Type getType() {
      return type;
    }

    /** @return the preferred UNIX file mode, e.g. {@code 0755}. */
    public int getMode() {
      return mode;
    }

    /** @return path of the entry, relative to the catalog root. */
    public String getPath() {
      return path;
    }

    /** @return name of the entry, within its parent directory. */
    public String getName() {
      final int s = path.lastIndexOf('/');
      return s < 0 ? path : path.substring(s + 1);
    }

    /** @return collection of entries below this one, if this is a directory. */
    public List<Entry> getChildren() {
      return Collections.unmodifiableList(children);
    }

    /** @return a copy of the file's contents. */
    public byte[] getBytes() {
      byte[] data = read(getPath());

      if (isScript(data)) {
        // Embed Gerrit's version number into the top of the script.
        //
        final String version = Version.getVersion();
        final int lf = RawParseUtils.nextLF(data, 0);
        if (version != null && lf < data.length) {
          byte[] versionHeader =
              Constants.encode("# From Gerrit Code Review " + version + "\n");

          ByteArrayOutputStream buf = new ByteArrayOutputStream();
          buf.write(data, 0, lf);
          buf.write(versionHeader, 0, versionHeader.length);
          buf.write(data, lf, data.length - lf);
          data = buf.toByteArray();
        }
      }

      return data;
    }

    private boolean isScript(byte[] data) {
      return data != null && data.length > 3 //
          && data[0] == '#' //
          && data[1] == '!' //
          && data[2] == '/';
    }
  }
}
