package org.workingfrog.i18n.util;

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

public class LogLevel {
    
    /** logs.
     * levels :
     *  - NONE   : no output,
     *  - L10N   : find missing keys for current language,
     *  - I18N   : locate objects without i18n behavior,
     *  - NAMING : identify mispelled keys or values hard coded in objects,
     *  - ALL    : all previous levels, less NONE ;-})
     *
     * combinations of levels L10N, I18N and NAMING :
     *  - IL : I18N + L10N,
     *  - IN : I18N + NAMING,
     *  - LN : L10N + NAMING,
     *  - LIN <=> ALL (not provided, ALL more efficient)
     */
    public static final LogLevel NONE   = new LogLevel("NONE");
    public static final LogLevel L10N   = new LogLevel("L10N");
    public static final LogLevel I18N   = new LogLevel("I18N");
    public static final LogLevel NAMING = new LogLevel("NAMING");
    public static final LogLevel IL     = new LogLevel("IL");
    public static final LogLevel IN     = new LogLevel("IN");
    public static final LogLevel LN     = new LogLevel("LN");
    public static final LogLevel ALL    = new LogLevel("ALL");
    
    /** LogLevel used in project */
    private static LogLevel current = NONE;
    
    /** used in comparison with current LogLevel */
    private static Set defaults = new HashSet();
    
    static {
        defaults.add(NONE);
        defaults.add(L10N);
        defaults.add(I18N);
        defaults.add(NAMING);
        defaults.add(ALL);
    }
    
    /** instance name */
    private final String name;
    
    private LogLevel (String name) { this.name = name; }
    
    private static boolean compare (LogLevel level, LogLevel combination) {

        if (IL.equals(combination)) {
            return level.equals(I18N) || level.equals(L10N);
        } else if (IN.equals(combination)) {
            return level.equals(I18N) || level.equals(NAMING);
        } else {
            return level.equals(L10N) || level.equals(NAMING);
        }
    }

    private static boolean bothAreLevels (LogLevel current, LogLevel level) {
        return defaults.contains(current) && defaults.contains(level);
    }

    private static boolean bothAreCombinations
        (LogLevel current, LogLevel level) {
        return !defaults.contains(current) && !defaults.contains(level);
    }

    public static void setCurrent (LogLevel level) {
        current = level;
    }

    public static void setCurrent (String level) {
        String ucLevel = level.toUpperCase();

        if (NONE.toString().equals(ucLevel)) {
            setCurrent(NONE);
        } else if (L10N.toString().equals(ucLevel)) {
            setCurrent(L10N);
        } else if (I18N.toString().equals(ucLevel)) {
            setCurrent(I18N);
        } else if (NAMING.toString().equals(ucLevel)) {
            setCurrent(NAMING);
        } else if (ALL.toString().equals(ucLevel)) {
            setCurrent(ALL);
        } else if (IL.toString().equals(ucLevel)) {
            setCurrent(IL);
        } else if (IN.toString().equals(ucLevel)) {
            setCurrent(IN);
        } else if (LN.toString().equals(ucLevel)) {
            setCurrent(LN);
        } else {
            throw new IllegalArgumentException("\"" + level + "\" is not a "
                + "valid i18n level");
        }
    }

    public static boolean isChecking (LogLevel level) {

        if (current.equals(ALL)) {
            return true;
        }

        if (bothAreLevels(current, level)) {
            return current.equals(level);
        } else if (bothAreCombinations(current, level)) {
            if (current.equals(IL)) {
                return level.toString().indexOf('I') != -1
                    || level.toString().indexOf('L') != -1;
            } else if (current.equals(IN)) {
                return level.toString().indexOf('I') != -1
                    || level.toString().indexOf('N') != -1;
            } else {
                return level.toString().indexOf('L') != -1
                    || level.toString().indexOf('N') != -1;
            }
        } else if (defaults.contains(current)) {
            return compare(current, level);
        } else {
            return compare(level, current);
        }
    }
    
    public String toString () { return name; }
    
    public static void main (String[] args) {
        
        System.out.println("testing NONE");
        LogLevel.setCurrent(NONE);
        System.out.println("checking ALL ? " + LogLevel.isChecking(ALL));
        System.out.println("checking I18N ? " + LogLevel.isChecking(I18N));
        System.out.println("checking NONE ? " + LogLevel.isChecking(NONE));
        
        System.out.println("\ntesting IN");
        LogLevel.setCurrent(IN);
        System.out.println("checking ALL ? " + LogLevel.isChecking(ALL));
        System.out.println("checking L10N ? " + LogLevel.isChecking(L10N));
        System.out.println("checking NAMING ? " + LogLevel.isChecking(NAMING));
        System.out.println("checking I18N ? " + LogLevel.isChecking(I18N));
    }
}
