/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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.apache.flex.compiler.internal.driver.js.flexjs;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.flex.compiler.constants.IASLanguageConstants;
import org.apache.flex.compiler.css.ICSSDocument;
import org.apache.flex.compiler.css.ICSSMediaQueryCondition;
import org.apache.flex.compiler.css.ICSSProperty;
import org.apache.flex.compiler.css.ICSSPropertyValue;
import org.apache.flex.compiler.css.ICSSRule;
import org.apache.flex.compiler.css.ICSSSelector;
import org.apache.flex.compiler.css.ICSSSelectorCondition;
import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
import org.apache.flex.compiler.internal.css.*;
import org.apache.flex.compiler.internal.css.codegen.CSSCompilationSession;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;

public class JSCSSCompilationSession extends CSSCompilationSession
{

    private ArrayList<String> requires;
    
    public String getEncodedCSS()
    {
        final ICSSDocument css = synthesisNormalizedCSS();
        StringBuilder sb = new StringBuilder();
        requires = new ArrayList<String>();
        encodeCSS(css, sb);
        if (sb.length() == 0)
        	return null;
        sb.append("];\n");
        for (String r : requires)
        {
            sb.append(JSGoogEmitterTokens.GOOG_REQUIRE.getToken() + "('" + formatQualifiedName(r) + "');\n");
        }

        return sb.toString();        
    }
    
    public String emitCSS()
    {
        final ICSSDocument css = synthesisNormalizedCSS();
        StringBuilder sb = new StringBuilder();
        sb.append("/* Generated by Apache Flex Cross-Compiler */\n");
        walkCSS(css, sb);
        return sb.toString();
    }
    
    private String fontFaceToString(CSSFontFace fontFace)
    {
        final StringBuilder result = new StringBuilder();
        result.append("@font-face {\n");
        result.append("    ");
        result.append("font-family: ");
        result.append(fontFace.getFontFamily() + ";\n");
        result.append("    ");
        result.append("font-style: ");
        result.append(fontFace.getFontStyle() + ";\n");
        result.append("    ");
        result.append("font-weight: ");
        result.append(fontFace.getFontStyle() + ";\n");
        result.append("    ");
        ArrayList<ICSSPropertyValue> sources = fontFace.getSources();
        for (ICSSPropertyValue src : sources)
        {
        	result.append("src: ");
        	result.append(src.toString() + ";\n");
        }
       	result.append("}\n");
        return result.toString();
    }
    
    private String cssRuleToString(ICSSRule rule)
    {
        final StringBuilder result = new StringBuilder();

        ImmutableList<ICSSMediaQueryCondition> mqList = rule.getMediaQueryConditions();
        boolean hasMediaQuery = !mqList.isEmpty();
        if (hasMediaQuery)
        {
            result.append("@media ");
            result.append(Joiner.on(" and ").join(rule.getMediaQueryConditions()));
            result.append(" {\n");
            result.append("    ");
        }

        ImmutableList<ICSSSelector> selectors = rule.getSelectorGroup();
        boolean firstOne = true;
        for (ICSSSelector selector : selectors)
        {
        	String s = selector.toString();
	        // add "." to type selectors that don't map cleanly
	        // to CSS type selectors to convert them to class
	    	// selectors.
	        if (!s.startsWith(".") && !s.startsWith("*") && !s.startsWith("#"))
	        {
	        	String condition = null;
        		int colon = s.indexOf(":");
	        	if (colon != -1)
	        	{
	        		condition = s.substring(colon);
	        		s = s.substring(0, colon);
	        	}
	        	if (!htmlElementNames.contains(s.toLowerCase()))
	        	{
	        		int pipe = s.indexOf("|");
	        		if (pipe != -1)
	        			s = s.substring(pipe + 1);
	        		s = "." + s;
	        	}
	        	if (condition != null)
	        		s = s + condition;
	        }
	        if (!firstOne)
	        	result.append(",\n");
	        result.append(s);
        }

        result.append(" {\n");
        for (final ICSSProperty prop : rule.getProperties())
        {
            if (!hasMediaQuery)
                result.append("    ");

            String propString = ((CSSProperty)prop).toCSSString();
            // skip class references since the won't work in CSS
            if (propString.contains("ClassReference"))
            	continue;
            result.append("    ").append(propString).append("\n");
        }
        if (hasMediaQuery)
            result.append("    }\n");

        result.append("}\n");

        return result.toString();
    }
    
    private void walkCSS(ICSSDocument css, StringBuilder sb)
    {
    	for (CSSFontFace fontFace : fontFaces)
    	{
    		sb.append(fontFaceToString(fontFace));
    	}
    	if (fontFaces.size() > 0)
    		sb.append("\n\n");
        ImmutableList<ICSSRule> rules = css.getRules();
        for (ICSSRule rule : rules)
        {
        	String s = cssRuleToString(rule);
        	if (s.startsWith("@media -flex-flash"))
        		continue;
        	if (s.startsWith(".global {"))
        		s = s.replace(".global {", "* {");
            sb.append(s);
            sb.append("\n\n");
        }
    }
    
    private void encodeCSS(ICSSDocument css, StringBuilder sb)
    {
        ImmutableList<ICSSRule> rules = css.getRules();
        boolean skipcomma = true;
        for (ICSSRule rule : rules)
        {
            String s = encodeRule(rule);
            if (s != null)
            {
                if (skipcomma)
                    skipcomma = false;
                else
                    sb.append(",\n");
                sb.append(s);
            }
        }
    }
    
    List<String> htmlElementNames = Arrays.asList(
    		"body",
    		"button",
    		"span"
    );
    
    private String encodeRule(ICSSRule rule)
    {
        final StringBuilder result = new StringBuilder();

        ImmutableList<ICSSMediaQueryCondition> mqlist = rule.getMediaQueryConditions();
        int n = mqlist.size();
        if (n > 0)
        {
            if (mqlist.get(0).toString().equals("-flex-flash"))
                return null;
            
            result.append(n);
            
            for (ICSSMediaQueryCondition mqcond : mqlist)
            {
                result.append(",\n");
                result.append("\"" + mqcond.toString() + "\"");
            }
        }
        else
            result.append(n);

        result.append(",\n");

        ImmutableList<ICSSSelector> slist = rule.getSelectorGroup();
        result.append(slist.size());

        for (ICSSSelector sel : slist)
        {
            result.append(",\n");
            String selName = this.resolvedSelectors.get(sel);
            if (selName == null || selName.equals("null"))
                result.append("\"" + sel.toString() + "\"");
            else
            {
            	selName = formatQualifiedName(selName);
                ImmutableList<ICSSSelectorCondition> conds = sel.getConditions();
                for (ICSSSelectorCondition cond : conds)
                    selName += cond.toString();
                result.append("\"" + selName + "\"");
            }
        }
        result.append(",\n");
        result.append("function() {");
        
        ImmutableList<ICSSProperty> plist = rule.getProperties();
        
        boolean firstProp = true;
        for (final ICSSProperty prop : plist)
        {
        	if (!firstProp)
        		result.append(";\n");
        	firstProp = false;
            result.append("this[\"" + prop.getName() + "\"] = ");
            ICSSPropertyValue value = prop.getValue();
            if (value instanceof CSSArrayPropertyValue)
            {
                ImmutableList<? extends ICSSPropertyValue> values = ((CSSArrayPropertyValue)value).getElements();
                result.append("[");
                boolean firstone = true;
                for (ICSSPropertyValue val : values)
                {
                    if (firstone)
                        firstone = false;
                    else
                        result.append(", ");
                    if (val instanceof CSSStringPropertyValue)
                    {
                        result.append("\"" + ((CSSStringPropertyValue)val).getValue() + "\"");
                    }
                    else if (val instanceof CSSColorPropertyValue)
                    {
                        result.append(new Integer(((CSSColorPropertyValue)val).getColorAsInt()));
                    }
                    else if (val instanceof CSSRgbColorPropertyValue)
                    {
                        result.append(new Integer(((CSSRgbColorPropertyValue)val).getColorAsInt()));
                    }
                    else if (value instanceof CSSRgbaColorPropertyValue)
                    {
                        //todo: handle alpha in the RGBA ?
                        result.append(new Integer(((CSSRgbaColorPropertyValue)value).getColorAsInt()));
                    }
                    else if (val instanceof CSSKeywordPropertyValue)
                    {
                        CSSKeywordPropertyValue keywordValue = (CSSKeywordPropertyValue)val;
                        String keywordString = keywordValue.getKeyword();
                        if (IASLanguageConstants.TRUE.equals(keywordString))
                            result.append("true");
                        else if (IASLanguageConstants.FALSE.equals(keywordString))
                            result.append("false");
                        else
                            result.append("\"" + ((CSSKeywordPropertyValue)val).getKeyword() + "\"");
                    }
                    else if (val instanceof CSSNumberPropertyValue)
                    {
                        result.append(new Double(((CSSNumberPropertyValue)val).getNumber().doubleValue()));
                    }
                    else if (val instanceof CSSURLAndFormatPropertyValue)
                    {
                        result.append("\"" + ((CSSURLAndFormatPropertyValue)val).toString() + "\"");
                    }
                    else
                    {
                        result.append("unexpected value type: " + val.toString());
                    }
                }
                result.append("]");
            }
            else if (value instanceof CSSStringPropertyValue)
            {
                result.append("\"" + ((CSSStringPropertyValue)value).getValue() + "\"");
            }
            else if (value instanceof CSSColorPropertyValue)
            {
                result.append(new Integer(((CSSColorPropertyValue)value).getColorAsInt()));
            }
            else if (value instanceof CSSRgbColorPropertyValue)
            {
                result.append(new Integer(((CSSRgbColorPropertyValue)value).getColorAsInt()));
            }
            else if (value instanceof CSSRgbaColorPropertyValue)
            {
                //todo: handle alpha in the RGBA ?
                result.append(new Integer(((CSSRgbaColorPropertyValue)value).getColorAsInt()));
            }
            else if (value instanceof CSSKeywordPropertyValue)
            {
                CSSKeywordPropertyValue keywordValue = (CSSKeywordPropertyValue)value;
                String keywordString = keywordValue.getKeyword();
                if (IASLanguageConstants.TRUE.equals(keywordString))
                    result.append("true");
                else if (IASLanguageConstants.FALSE.equals(keywordString))
                    result.append("false");
                else
                    result.append("\"" + ((CSSKeywordPropertyValue)value).getKeyword() + "\"");
            }
            else if (value instanceof CSSNumberPropertyValue)
            {
                result.append(new Double(((CSSNumberPropertyValue)value).getNumber().doubleValue()));
            }
            else if (value instanceof CSSFunctionCallPropertyValue)
            {
                final CSSFunctionCallPropertyValue functionCall = (CSSFunctionCallPropertyValue)value;
                if ("ClassReference".equals(functionCall.name))
                {
                    final String className = CSSFunctionCallPropertyValue.getSingleArgumentFromRaw(functionCall.rawArguments);
                    if ("null".equals(className))
                    {
                        // ClassReference(null) resets the property's class reference.
                        result.append("null");
                    }
                    else
                    {
                        result.append(formatQualifiedName(className));
                        requires.add(className);
                    }
                }
                else if ("url".equals(functionCall.name))
                {
                    final String urlString = CSSFunctionCallPropertyValue.getSingleArgumentFromRaw(functionCall.rawArguments);
                    result.append("\"" + urlString + "\"");
                }
                else if ("PropertyReference".equals(functionCall.name))
                {
                    // TODO: implement me
                }
                else if ("calc".equals(functionCall.name))
                {
                    // TODO: implement me
                }
                else if ("Embed".equals(functionCall.name))
                {
                    // TODO: implement me
                    /*
                    final ICompilerProblem e = new CSSCodeGenProblem(
                            new IllegalStateException("Unable to find compilation unit for " + functionCall));
                    problems.add(e);
                    */
                }
                else
                {
                    assert false : "CSS parser bug: unexpected function call property value: " + functionCall;
                    throw new IllegalStateException("Unexpected function call property value: " + functionCall);
                }
            }
        }
        result.append("}");

        return result.toString();

    }
    
    @Override
    protected boolean keepRule(ICSSRule newRule)
    {
    	if (super.keepRule(newRule))
    		return true;
    	
    	// include all rules not found in defaults.css
    	// theoretically, defaults.css rules were
    	// properly added in the super call.
    	String sp = newRule.getSourcePath();
    	if (!sp.contains("defaults.css"))
    		return true;
    	
        return false;
    }

    private String formatQualifiedName(String name)
    {
    	/*
    	if (name.contains("goog.") || name.startsWith("Vector."))
    		return name;
    	if (name.startsWith("."))
    	{
    		return "." + name.substring(1).replaceAll("\\.", "_");
    	}
    	name = name.replaceAll("\\.", "_");
    	*/
    	return name;
    }

}
