// Copyright 2009 Google Inc. All Rights Reserved.

package org.unicode.cldr.icu;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.List;

import org.unicode.cldr.icu.ICUResourceWriter.Resource;
import org.unicode.cldr.icu.ICUResourceWriter.ResourceTable;
import org.unicode.cldr.icu.ResourceSplitter.ResultInfo;

class ICUWriter {
  private static final String LINESEP = System.getProperty("line.separator");
  private static final String BOM = "\uFEFF";
  private static final String CHARSET = "UTF-8";

  private final String dstDirName;
  private final ICULog log;
  private final ResourceSplitter splitter;

  ICUWriter(String dstDirName, ICULog log, ResourceSplitter splitter) {
    this.dstDirName = dstDirName;
    this.log = log;
    this.splitter = splitter;
  }

//  private static final ResourceSplitter debugSplitter;
//  static {
//    List<SplitInfo> splitInfos = new ArrayList<SplitInfo>();
//    splitInfos.add(new SplitInfo("/Languages", "lang"));
//    splitInfos.add(new SplitInfo("/LanguagesShort", "lang"));
//    splitInfos.add(new SplitInfo("/Scripts", "lang"));
//    splitInfos.add(new SplitInfo("/Types", "lang"));
//    splitInfos.add(new SplitInfo("/Variants", "lang"));
//    splitInfos.add(new SplitInfo("/codePatterns", "lang"));
//    splitInfos.add(new SplitInfo("/Countries", "terr", "/Territories"));
//    splitInfos.add(new SplitInfo("/Currencies", "curr"));
//    splitInfos.add(new SplitInfo("/CurrencyPlurals", "curr"));
//    splitInfos.add(new SplitInfo("/CurrencyUnitPatterns", "curr"));
//    splitInfos.add(new SplitInfo("/zoneStrings", "zone"));
//
//    debugSplitter = new ResourceSplitter("/tmp/ldml", splitInfos);
//  }

  public void writeResource(Resource res, String sourceInfo) {
    if (splitter == null) {
      String outputFileName = dstDirName + "/" + res.name + ".txt";
      writeResource(res, sourceInfo, outputFileName);
    } else {
      File rootDir = new File(dstDirName);
      List<ResultInfo> result = splitter.split(rootDir, (ResourceTable) res);

      for (ResultInfo info : result) {
        res = info.root;
        String outputFileName = info.directory.getAbsolutePath() + "/" + res.name + ".txt";
        writeResource(res, sourceInfo, outputFileName);
      }
    }
  }

  private void writeResource(Resource set, String sourceInfo, String outputFileName) {
    try {
      log.log("Writing " + outputFileName);
      FileOutputStream file = new FileOutputStream(outputFileName);
      BufferedOutputStream writer = new BufferedOutputStream(file);
      writeHeader(writer, sourceInfo);

      for (Resource res = set; res != null; res = res.next) {
        res.sort();
      }

      for (Resource res = set; res != null; res = res.next) {
        res.write(writer, 0, false);
      }

      writer.flush();
      writer.close();
    } catch (Resource.MalformedResourceError mre) {
      String where = set.findResourcePath(mre.offendingResource);
      log.error("Could not write resource " + where + ". " + mre.toString(), mre);
      if (!new File(outputFileName).delete()) {
        log.error("Failed to delete file");
      }
      System.exit(1);
    } catch (Exception ie) {
      log.error("Could not write resource." + ie.toString(), ie);
      if (!new File(outputFileName).delete()) {
        log.error("Failed to delete file");
      }
      System.exit(1);
    }
  }

  private void writeLine(OutputStream writer, String line) {
    try {
      byte[] bytes = line.getBytes(CHARSET);
      writer.write(bytes, 0, bytes.length);
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      System.exit(1);
    }
  }

  private void writeHeader(OutputStream writer, String fileName) {
    writeBOM(writer);
    Calendar c = Calendar.getInstance();
    StringBuilder buffer = new StringBuilder();
    buffer.append("// ***************************************************************************")
    .append(LINESEP)
    .append("// *")
    .append(LINESEP)
    .append("// * Copyright (C) ")
    .append(c.get(Calendar.YEAR))
    .append(" International Business Machines")
    .append(LINESEP)
    .append("// * Corporation and others.  All Rights Reserved.")
    .append(LINESEP)
    .append("// * Tool: com.ibm.icu.dev.tool.cldr.LDML2ICUConverter.java")
    .append(LINESEP);
    // buffer.append("// * Date & Time: ")
    // .append(c.get(Calendar.YEAR))
    // .append("/")
    // .append(c.get(Calendar.MONTH) + 1)
    // .append("/")
    // .append(c.get(Calendar.DAY_OF_MONTH))
    // .append(" ")
    // .append(c.get(Calendar.HOUR_OF_DAY))
    // .append(COLON)
    // .append(c.get(Calendar.MINUTE))
    // .append(LINESEP);
    //         String ver = LDMLUtilities.getCVSVersion(fileName);
    //         if (ver == null) {
    //             ver = "";
    //         } else {
    //             ver = " v" + ver;
    //         }

    String tempdir = fileName.replace('\\','/');
    int index = tempdir.indexOf("/common");
    if (index > -1) {
      tempdir = "<path>" + tempdir.substring(index, tempdir.length());
    } else {
      index = tempdir.indexOf("/xml");
      if (index > -1) {
        tempdir = "<path>" + tempdir.substring(index, tempdir.length());
      } else {
        tempdir = "<path>/" + tempdir;
      }
    }
    buffer.append("// * Source File:" + tempdir)
    .append(LINESEP)
    .append("// *")
    .append(LINESEP)
    .append("// ***************************************************************************")
    .append(LINESEP);
    writeLine(writer, buffer.toString());
  }

  private void writeBOM(OutputStream buffer) {
    try {
      byte[] bytes = BOM.getBytes(CHARSET);
      buffer.write(bytes, 0, bytes.length);
    } catch(Exception e) {
      log.error(e.getMessage(), e);
    }
  }
}