package gov.cms.grouper.snf.lego;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class CsvHelper<T> {

  public static final String regex = "\"[ ]*,[ ]*\"";

  private final List<String> lines;
  private final CsvBuilder<T> builder;
  private final boolean header;

  public CsvHelper(List<String> lines, CsvBuilder<T> builder, boolean header) {
    this.lines = lines;
    this.builder = builder;
    this.header = header;
  }

  public static <T> CsvHelper<T> of(List<String> lines, CsvBuilder<T> builder, boolean header) {
    return new CsvHelper<T>(lines, builder, header);
  }

  public List<String[]> getRows(List<String> lines) {
    List<String[]> rows = new ArrayList<>();
    int begin = (this.header) ? 1 : 0;
    for (int i = begin; i < lines.size(); i++) {
      String line = SnfUtils.clean(lines.get(i));
      if (SnfUtils.isBlank(line) == false) {
        // remove begin and end quote
        String[] row = line.split(CsvHelper.regex);
        if (row[0].charAt(0) == '"') {
          row[0] = row[0].substring(1);
          String last = row[row.length - 1];
          row[row.length - 1] = last.substring(0, last.length() - 1);
        }
        for (int c = 0; c < row.length; c++) {
          row[c] = SnfUtils.clean(row[c]);
        }

        rows.add(row);
      }
    }

    return rows;
  }

  public List<T> getData(CsvBuilder<T> build, List<String[]> rows) {
    List<T> result = new ArrayList<>(rows.size());
    for (String[] row : rows) {
      T item = build.get(row);
      result.add(item);
    }
    return result;
  }

  public List<T> load(List<String> lines) {
    List<String[]> rows = this.getRows(lines);
    List<T> result = this.getData(this.builder, rows);
    return result;
  }

  public Set<T> load() {
    Set<T> result = SnfUtils.toSet(this.load(this.lines));
    return result;
  }

  public static <ITEMT> List<ITEMT> load(CsvBuilder<ITEMT> build, List<String> lines,
      boolean header) {
    CsvHelper<ITEMT> helper = new CsvHelper<>(null, build, header);
    return helper.load(lines);
  }

}
