// Copyright (C) 2015 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.git;

import org.slf4j.Logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TabFile {
  public interface Parser {
    public String parse(String str);
  }

  public static Parser TRIM = new Parser() {
        public String parse(String str) {
           return str.trim();
        }
      };


  protected static class Row {
    public String left;
    public String right;

    public Row(String left, String right) {
      this.left = left;
      this.right = right;
    }
  }

  protected static List<Row> parse(String text, String filename, Parser left,
      Parser right, ValidationError.Sink errors) throws IOException {
    List<Row> rows = new ArrayList<Row>();
    BufferedReader br = new BufferedReader(new StringReader(text));
    String s;
    for (int lineNumber = 1; (s = br.readLine()) != null; lineNumber++) {
      if (s.isEmpty() || s.startsWith("#")) {
        continue;
      }

      int tab = s.indexOf('\t');
      if (tab < 0) {
        errors.error(new ValidationError(filename, lineNumber,
            "missing tab delimiter"));
        continue;
      }

      Row row = new Row(s.substring(0, tab), s.substring(tab + 1));
      rows.add(row);

      if (left != null) {
        row.left = left.parse(row.left);
      }
      if (right != null) {
        row.right = right.parse(row.right);
      }
    }
    return rows;
  }

  protected static Map<String, String> toMap(List<Row> rows) {
    Map<String, String> map = new HashMap<>(rows.size());
    for (Row row : rows) {
      map.put(row.left, row.right);
    }
    return map;
  }

  protected static String asText(String left, String right,
      Map<String, String> entries) {
    if (entries.isEmpty()) {
      return null;
    }

    List<Row> rows = new ArrayList<>(entries.size());
    for (String key : sort(entries.keySet())) {
      rows.add(new Row(key, entries.get(key)));
    }
    return asText(left, right, rows);
  }

  protected static String asText(String left, String right, List<Row> rows) {
    if (rows.isEmpty()) {
      return null;
    }

    left = "# " + left;
    int leftLen = left.length();
    for (Row row : rows) {
      leftLen = Math.max(leftLen, row.left.length());
    }

    StringBuilder buf = new StringBuilder();
    buf.append(pad(leftLen, left));
    buf.append('\t');
    buf.append(right);
    buf.append('\n');

    buf.append('#');
    buf.append('\n');

    for (Row row : rows) {
      buf.append(pad(leftLen, row.left));
      buf.append('\t');
      buf.append(row.right);
      buf.append('\n');
    }
    return buf.toString();
  }

  protected static <T extends Comparable<? super T>> List<T> sort(Collection<T> m) {
    ArrayList<T> r = new ArrayList<>(m);
    Collections.sort(r);
    return r;
  }

  protected static String pad(int len, String src) {
    if (len <= src.length()) {
      return src;
    }

    StringBuilder r = new StringBuilder(len);
    r.append(src);
    while (r.length() < len) {
      r.append(' ');
    }
    return r.toString();
  }

  public static ValidationError.Sink createLoggerSink(String file, Logger log) {
    return ValidationError.createLoggerSink("Error parsing file " + file + ": ",
        log);
  }
}

@@ -1052,24 +1052,34 @@
 ser() %7B%0A    
+@Override%0A
     public S
@@ -1111,20 +1111,16 @@
 %0A       
-    
 return s
@@ -1138,25 +1138,16 @@
     
-    %7D%0A    
+%7D%0A
   %7D;%0A%0A
-%0A
   pr
@@ -1511,19 +1511,16 @@
 rayList%3C
-Row
 %3E();%0A   

Fix Eclipse warnings and code style