// 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] == '/';
    }
  }
}
