package org.unicode.cldr.tool;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.unicode.cldr.util.CldrUtility;
import org.unicode.cldr.util.SimpleHtmlParser;
import org.unicode.cldr.util.SimpleHtmlParser.Type;

import com.ibm.icu.dev.util.BagFormatter;

/**
 * Run this code to extract the ISO currency data from a file.
 * Use -Dinput=xxx for the input file, and -Doutput=xxx for the output file
 * 
 * @author markdavis
 */
public class ExtractIsoCurrencyData {
    private static final boolean VERBOSE = true;

    private static final Matcher HAS_DATE = Pattern.compile(
        "last modified.*([0-9]{4}-[0-9]{2}-[0-9]{2})",
        Pattern.DOTALL).matcher("");

    public static void main(String[] args) throws IOException {
        final String inputFile = CldrUtility.getProperty("input");
        BufferedReader in;
        if (inputFile == null) {
            in = CldrUtility.getUTF8Data("currency_codes_list-1.htm");
        } else {
            in = BagFormatter.openUTF8Reader("", inputFile);
        }
        // NOTE: UTIL_DATA_DIR is required here because it is used as an output directory.
        final String outputFile = CldrUtility.getProperty("output", CldrUtility.UTIL_DATA_DIR
            + "/currencycodeslist.txt");
        PrintWriter out = BagFormatter.openUTF8Writer(null, outputFile);
        try {
            String version = null;
            String[][] parts = new String[5][5];
            int count = 0;

            boolean inContent = false;
            // if the table level is 1 (we are in the main table), then we look for <td>...</td><td>...</td>. That means
            // that we have column 1 and column 2.

            SimpleHtmlParser simple = new SimpleHtmlParser().setReader(in);
            StringBuilder result = new StringBuilder();
            boolean hadPop = false;
            int column = -1;
            int row = -1;
            main: while (true) {
                Type x = simple.next(result);
                // System.out.println(x + "\t" + result);
                switch (x) {
                case ELEMENT: // with /table we pop the count
                    if (SimpleHtmlParser.equals("tr", result)) {
                        if (hadPop) {
                            for (int i = 0; i < parts.length; ++i) {
                                boolean empty = true;
                                for (int j = 0; j < parts[i].length; ++j) {
                                    parts[i][j] = parts[i][j].replace("&nbsp;", " ");
                                    parts[i][j] = parts[i][j].replace("\u2020", " ");
                                    parts[i][j] = parts[i][j].replace("\u2021", " ");
                                    parts[i][j] = parts[i][j].replace("\u00A0", " ");
                                    parts[i][j] = parts[i][j].trim();
                                    empty &= parts[i][j].length() == 0;
                                }
                                if (empty) {
                                    continue;
                                }
                                if (parts[i][0].length() == 0) {
                                    parts[i][0] = i == 0 ? "ZZ" : parts[0][0]; // hack because of iso format
                                } else if (parts[i][0].equals("Entity")) {
                                    continue;
                                }
                                if (parts[i][1].equals("Special settlement currencies")) {
                                    continue;
                                } else if (parts[i][1].equals("No universal currency")) {
                                    parts[i][2] = "XXX";
                                    parts[i][3] = "999";
                                }
                                // fix numbers to match old style
                                if (VERBOSE)
                                    System.out.println("\tDATA: " + Arrays.asList(parts[i]));
                                int num = parts[i][3].equals("Nil") ? -1 : Integer.parseInt(parts[i][3]);
                                parts[i][3] = String.valueOf(num);
                                out.println(CldrUtility.join(parts[i], "\t").trim());
                                count++;
                                // Data data = new Data(country, parts[i][1], parts[i][3]);
                                // codeList.put(parts[i][2], data);
                            }
                            column = -1;
                            row = -1;
                        } else {
                            column = 0;
                            row = 0;
                            for (int i = 0; i < parts.length; ++i) {
                                for (int j = 0; j < parts[i].length; ++j) {
                                    parts[i][j] = "";
                                }
                            }
                        }
                    } else if (SimpleHtmlParser.equals("td", result)
                        || SimpleHtmlParser.equals("th", result)) {
                        if (hadPop) {
                            column++;
                            row = 0;
                        }
                    } else if (SimpleHtmlParser.equals("br", result)) { // because ISO has screwy format
                        row++;
                    }
                    break;
                case ELEMENT_CONTENT:
                    if (column >= 0) {
                        parts[row][column] += result;
                    }
                    break;
                case QUOTE:
                    if (HAS_DATE.reset(result).find()) {
                        version = HAS_DATE.group(1);
                    }
                    break;
                case ELEMENT_POP:
                    hadPop = true;
                    break;
                case ELEMENT_START:
                    hadPop = false;
                    break;
                case DONE:
                    break main;
                case ELEMENT_END:
                case ATTRIBUTE:
                case ATTRIBUTE_CONTENT:
                    break; // for debugging
                }
            }
            in.close();
            if (version == null) {
                throw new IllegalArgumentException("Missing version; ISO file format probably changed.");
            }
            if (count < 50) {
                throw new IllegalArgumentException("Data too small; ISO file format probably changed.");
            }
            out.println("Last modified " + version);
        } catch (IOException e) {
            throw new IllegalArgumentException("Can't read currency file " + e.getMessage());
        }
        out.close();
    }

    /**
     * Was code to check when we moved from flat file to html to alert on differences. Not necessary any more.
     * 
     * @throws IOException
     */
    // public void CheckISOCurrencyParser() throws IOException {
    // Relation<String, Data> codeList = new Relation(new TreeMap(), TreeSet.class, null);
    // Relation<String, Data> codeListHtml = new Relation(new TreeMap(), TreeSet.class, null);
    //
    // String version = IsoCurrencyParser.getFlatList(codeList);
    // String versionHtml = IsoCurrencyParser.getHtmlList(codeListHtml); // getFlatList
    // assertEquals("Versions don't match", version, versionHtml);
    // Set<String> keys = new TreeSet(codeList.keySet());
    // keys.addAll(codeListHtml.keySet());
    // for (String key : keys) {
    // Set<Data> flat = codeList.getAll(key);
    // Set<Data> html = codeListHtml.getAll(key);
    // if (flat == null || !flat.equals(html)) {
    // if (flat != null) {
    // Set inFlatOnly = new TreeSet(flat);
    // if (html != null) inFlatOnly.removeAll(html);
    // if (inFlatOnly.size() != 0) errln(key + "\t\tflat: " + inFlatOnly);
    // }
    // if (html != null) {
    // Set inHtmlOnly = new TreeSet(html);
    // if (flat != null) inHtmlOnly.removeAll(flat);
    // if (inHtmlOnly.size() != 0) errln("\t" + key + "\thtml: " + inHtmlOnly);
    // }
    // }
    // }
    // System.out.println(codeList);
    // }
}
