/*
 * Copyright 2004-2005 The Trix Development Team.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.trix.cuery.filter;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.ArrayUtils;

import org.trix.cuery.CSS;
import org.trix.cuery.StyleContext;
import org.trix.cuery.util.I18nUtil;

import org.w3c.css.sac.CSSException;
import org.w3c.dom.Element;

/**
 * DOCUMENT.
 * 
 * @author <a href="mailto:Teletha.T@gmail.com">Teletha Testarossa</a>
 * @version $ Id: PseudoClassFilter.java,v 1.05 2005/12/25 09:44:02 Teletha Exp $
 */
public class PseudoClassFilter extends AbstractPseudoFilter {

    /** The name of pseudo classes in CSS2. */
    private static final String[] PSEUDO_CLASSES_CSS2 = {"link", "visited", "active", "hover", "focus"};

    /** The name of pseudo classes in CSS3. */
    private static final String[] PSEUDO_CLASSES_CSS3 = {"enabled", "default", "disabled", "checked", "in-range",
            "invalid", "optional", "out-of-range", "read-only", "read-write", "required", "target", "valid"};

    /** The state pool. */
    private static final Map STATES = new HashMap();

    // initialize
    static {
        Field[] fields = CSS.class.getDeclaredFields();

        for (int i = 0; i < fields.length; i++) {
            try {
                String name = fields[i].getName().toLowerCase().replace('_', '-');

                if (ArrayUtils.indexOf(PSEUDO_CLASSES_CSS2, name) != -1
                        || ArrayUtils.indexOf(PSEUDO_CLASSES_CSS3, name) != -1) {
                    STATES.put(name, fields[i].get(null));
                }
            } catch (Exception e) {
                // do nothing
            }
        }
    }

    /** The pseudo name. */
    private String name;

    /** The pseudo state. */
    private int state;

    /**
     * Create PseudoClassFilter instance.
     * 
     * @param name A pseudo name.
     */
    public PseudoClassFilter(String name) {
        Integer integer = (Integer) STATES.get(name);

        if (integer == null) {
            throw new CSSException(I18nUtil.getText("parser.invalidPseudo", name));
        }

        this.name = name;
        this.state = integer.intValue();
    }

    /**
     * @see org.trix.cuery.filter.Filter#accept(org.w3c.dom.Element)
     */
    public boolean accept(Element target) {
        StyleContext context = StyleContext.getContext(target);
        return context.hasState(state);
    }

    /**
     * @see org.trix.cuery.filter.AbstractPseudoFilter#getPseudoName()
     */
    protected String getPseudoName() {
        return name;
    }
}
