// Copyright 2009 Google Inc. All Rights Reserved.

package org.unicode.cldr.icu;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.unicode.cldr.icu.LDML2ICUConverter.DocumentPair;
import org.unicode.cldr.icu.LDML2ICUConverter.LDMLServices;
import org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.CLDRFile.DraftStatus;

class LDML2ICUInputLocale {
    private final LDMLServices services;
    private final boolean notOnDisk;
    private final String locale;
    private final CLDRFile rawFile;
    private final CLDRFile file;
    private final CLDRFile specialsFile;
    private CLDRFile resolved;

    /** Cache results of beenHere. See {@link #beenHere}. */
    private final Set<String> alreadyDone = new HashSet<String>();

    public boolean isNotOnDisk() {
        return notOnDisk;
    }

    public String getLocale() {
        return locale;
    }

    public CLDRFile getFile() {
        return file;
    }

    public CLDRFile getSpecialsFile() {
        return specialsFile;
    }

    @Override
    public String toString() {
        return "{"
            + "notOnDisk=" + notOnDisk
            + " locale=" + locale
            + " rawFile=" + abbreviated(rawFile)
            + " file=" + abbreviated(file)
            + " specialsFile=" + abbreviated(specialsFile)
            + " resolved=" + abbreviated(resolved)
            + "}";
    }

    private String abbreviated(Object raw) {
        if (raw == null) {
            return null;
        }
        String result = raw.toString();
        if (result.length() <= 100) {
            return result;
        }
        return result.substring(0, 100) + "...";
    }

    public CLDRFile resolved() {
        if (resolved == null) {
            if (services.cldrFactory() != null) {
                resolved = services.cldrFactory().make(locale, true, DraftStatus.contributed);
            } else {
                System.err.println("Error: cldrFactory is null in \"resolved()\"");
                System.err.flush();
                System.exit(1);
            }
        }
        return resolved;
    }

    public LDML2ICUInputLocale(CLDRFile fromFile, LDMLServices services) {
        this.services = services;
        this.notOnDisk = true;
        this.locale = fromFile.getLocaleID();
        this.rawFile = this.file = this.resolved = fromFile;
        this.specialsFile = null;
    }

    public LDML2ICUInputLocale(String locale, LDMLServices services) {
        this.services = services;
        this.notOnDisk = false;
        this.locale = locale;
        this.rawFile = services.cldrFactory().make(locale, false);
        this.specialsFile = services.getSpecialsFile(locale);
        if (specialsFile != null) {
            this.file = (CLDRFile) rawFile.cloneAsThawed();
            this.file.putAll(specialsFile, CLDRFile.MERGE_REPLACE_MINE);
        } else {
            this.file = rawFile; // frozen
        }
    }

    public Set<String> getByType(String baseXpath, String element) {
        return getByType(baseXpath, element, LDMLConstants.TYPE);
    }

    public Set<String> getByType(String baseXpath, String element, String attribute) {
        Set<String> typeList = new HashSet<String>();
        for (Iterator<String> iter = file.iterator(baseXpath); iter.hasNext();) {
            String somePath = iter.next();
            String type = XPPUtil.getAttributeValue(somePath, element, attribute);
            if (type == null) {
                continue;
            } else {
                typeList.add(type);
            }
        }
        return typeList;
    }

    public String getBasicAttributeValue(String xpath, String attribute) {
        return XPPUtil.getBasicAttributeValue(file, xpath, attribute);
    }

    public String findAttributeValue(String xpath, String attribute) {
        return XPPUtil.findAttributeValue(file, xpath, attribute);
    }

    public String getResolvedString(String xpath) {
        String rv = file.getStringValue(xpath);
        if (rv == null) {
            rv = resolved().getStringValue(xpath);
        }
        return rv;
    }

    /**
     * Determine whether a particular section has been done
     * 
     * @param where
     *            the name of the section, i.e. LDMLConstants.IDENTITY
     * @return true if this part has already been processed, otherwise
     *         false. If false, it will return true the next time called.
     */
    public boolean beenHere(String where) {
        if (alreadyDone.contains(where)) {
            return true;
        }

        alreadyDone.add(where);
        return false;
    }

    public boolean isPathNotConvertible(String xpath) {
        return isPathNotConvertible(file, xpath);
    }

    public boolean isPathNotConvertible(CLDRFile f, String xpath) {
        String alt = XPPUtil.getBasicAttributeValue(f, xpath, "alt");
        if (alt != null) {
            return true;
        }
        return !services.xpathListContains(f.getFullXPath(xpath)) && f.isHere(xpath);
    }

    // ====== DOM compatibility
    // This cache is set/retrieved by LDML2ICUConverter.getDocumentPair(LDML2ICUInputLocale)

    private DocumentPair docPair = null;

    public DocumentPair getDocumentPair() {
        return docPair;
    }

    public void setDocumentPair(DocumentPair docPair) {
        this.docPair = docPair;
    }
}