/*
 *
 *  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.royale.compiler.internal.codegen.databinding;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.apache.royale.compiler.constants.IASKeywordConstants;
import org.apache.royale.compiler.definitions.IClassDefinition;
import org.apache.royale.compiler.definitions.IConstantDefinition;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.IFunctionDefinition;
import org.apache.royale.compiler.definitions.IInterfaceDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.definitions.IVariableDefinition;
import org.apache.royale.compiler.internal.codegen.databinding.WatcherInfoBase.WatcherType;
import org.apache.royale.compiler.internal.projects.RoyaleProject;
import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.compiler.problems.MXMLDatabindingSourceNotBindableProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.IFunctionCallNode;
import org.apache.royale.compiler.tree.as.IIdentifierNode;
import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;


/**
 * Analyzes a node that represents a binding expression, an generates all the
 * WatcherInfo objects needed to describe the mx.internal.binding.Watchers we will code gen.
 */
public class WatcherAnalyzer
{
    /**
     * Constructor
     * 
     * @param bindingDataBase - is where the results of the analysis are stored
     * @param problems - is where any semantic problems discuvered during analysis are reported
     * @param bindingInfo - is an object created by the BindingAnalyzer to represing the mx.internal.binding.Binding object that will control
     *          this binding expression
     */
    public WatcherAnalyzer(
            BindingDatabase bindingDataBase,
            Collection<ICompilerProblem> problems,
            BindingInfo bindingInfo,
            ICompilerProject project)
    {
        this.bindingDataBase = bindingDataBase;
        this.problems = problems;
        this.bindingInfo = bindingInfo;
        this.project = project;
    }
    
    //------------------- private state -----------------------------
  
    private final BindingDatabase bindingDataBase;
    private final Collection<ICompilerProblem> problems;
    private final BindingInfo bindingInfo;
    private final ICompilerProject project;

    //------------------------ public functions ----------------------
    
    /**
     * structure to holder onto temporary information is we do a
     *  recursive descent parse of the binding expression node
     */
    static class AnalysisState
    {
        /**
         * If true, we we will chain watchers as we find new variables. ex: {a.b}
         * If false, we will generate independent watchers ex: { foo(a, b) }
         */
        public boolean chaining = false;
        
        /**
         *  as we are building up a chain of dependent property watchers, curChain
         *  points to the lowest "link" that was build. Will be null if we are not yet building 
         *  up a chain.
         *  
         *  It is of the specific type "PropertyWatcherInfo", because that is the only
         *  info class that knows how to chain.
         */
        public WatcherInfoBase curChain = null;
        
        /**
         * While we are parsing a function call node, this will
         * hold the definition for it's name
         */
        public IDefinition functionCallNameDefintion = null;
        
        /**
         * If we are parsing an expression like model.a.b.c.d, 
         *  where "Model" is an ObjectProxy or Model tag
         */
        public boolean isObjectProxyExpression = false;
        
        /**
         * the event name(s) that the ObjectProxy/Model dispatches.
         * We need to pass this back up the parse chain so that the subsequent 
         * property watchers know the event name(s)
         */
        List<String> objectProxyEventNames = null;
    }
    
    public void analyze()
    {
        // When there are multiple expression (concatenating case), then we can
        // just analyze each one independently
         for (IExpressionNode expression : bindingInfo.getExpressionNodesForGetter())
        {
             doAnalyze(expression, new AnalysisState());                  // recursively analyze the sub-tree.   
        }
    }
    
    private  void doAnalyze(IASNode node, AnalysisState state)
    {
        ASTNodeID id = node.getNodeID();
        switch(id)
        {
            case IdentifierID:
                analyzeIdentifierNode((IIdentifierNode)node, state);
                break;
            case MemberAccessExpressionID:
                andalyzeMemberAccessExpression( (IMemberAccessExpressionNode) node, state);
                break;
            case FunctionCallID:
                analyzeFunctionCallNode((IFunctionCallNode) node, state);
                break;
            default:
                // For other kinds of nodes, just recurse down looking for something to do
               analyzeChildren(node, state);
                break;
        } 
    }

    private void analyzeChildren(IASNode node, AnalysisState state)
    {
        // For other kinds of nodes, just recurse down looking for something to do
        for (int i=0; i<node.getChildCount(); ++i)
        {
            IASNode ch = node.getChild(i);
            doAnalyze(ch, state);
        }
    }
    
    
    private void analyzeFunctionCallNode(IFunctionCallNode node, AnalysisState state)
    {
        
        assert state.functionCallNameDefintion == null;     // we can't nest (yet?)
        
        // First, let's get the node the represents the function name.
        // That's the one that will have the binding metadata
        IExpressionNode nameNode = node.getNameNode();
        
        IDefinition nameDef = nameNode.resolve(project);
        
        // we ignore non-bindable functions
        // we also ignore functions that don't resolve - they are dynamic, and hence
        // not watchable
        if (nameDef!=null && nameDef.isBindable())
        {
            state.functionCallNameDefintion = nameDef;
        }
        
        analyzeChildren(node, state);           // continue down looking for watchers.
        
        state.functionCallNameDefintion = null; // now we are done with the function call node
      
    }
   
    private void andalyzeMemberAccessExpression(IMemberAccessExpressionNode node, AnalysisState state)
    {
        final boolean wasChaining = state.chaining;

        
        state.chaining = true;      // member access expressions require chained watcher.
                                    // ex: {a.b} - the watcher for b will be a child of a
        final IExpressionNode left = node.getLeftOperandNode();
        final IExpressionNode right = node.getRightOperandNode();
  
        final IDefinition leftDef = left.resolve(project);
        final IDefinition rightDef = right.resolve(project);
        if (leftDef instanceof IClassDefinition)
        {
            // In this case, is foo.prop, where "foo" is a class name.
            // We can skip over the left side ("foo"), because when we
            // analyze the right side we will still know what it is.
            doAnalyze(right, state); 
        }
        else
        {
            if ((rightDef == null) && (leftDef != null))
            {
                // maybe we are something like ObjectProxy.dynamicProperty
                // (someone who extends ObjectProxy, like Model)
                ITypeDefinition leftType= leftDef.resolveType(project);  
                RoyaleProject project = (RoyaleProject)this.project;
                String objectProxyClass = project.getObjectProxyClass();
                boolean isObjectProxy = leftType==null ? false : leftType.isInstanceOf(objectProxyClass, project);
    
                // If we are proxy.prop, we set this info into the parse state. This does two things:
                //      1) tells downstream properties that they can be dynamic, and hence don't need
                //          to be resolvable.
                //      2) Stores off the event names from the proxy so that the chained property watchers
                //          can use the info
                if (isObjectProxy)
                {
                    state.isObjectProxyExpression = true;
                    state.objectProxyEventNames = leftType.getBindableEventNames();
                }
                else
                {
                    String proxyClass = project.getProxyBaseClass();
                    boolean isProxy = leftType==null ? false : leftType.isInstanceOf(proxyClass, project);
                    if (isProxy)
                    {
                        state.isObjectProxyExpression = true;
                        state.objectProxyEventNames = leftType.getBindableEventNames();
                    }
                }
            }
            doAnalyze(left, state);
            doAnalyze(right, state); 
       
        }
        
        // If we are finished generating the chain for the top member access expression,
        // then shut off chaining. Otherwise the next variable we see might get added to this chain,
        // even though is it not related
        if (!wasChaining)
        {
            state.chaining = false;
            state.curChain = null;
        }
        
        // If we are finished with a chain of ObjectProxy.prop.prop things,
        // then clear out the remembered info from the ObjectProxy.
        // Note that this "termination condition" is quite different from the one above.
        // Above the logic was "I'm going to set this, recursively apply to children, then clear.
        // In this case, the logic is "I'm going to set and forget, because my PARENT want these results.
        // Eventually I can clear it when my I can determine that my parent is not part of the chain.
        if ( state.isObjectProxyExpression)
        {
            IASNode parent = node.getParent();
            if (!(parent instanceof IMemberAccessExpressionNode))
            {
                state.isObjectProxyExpression = false;
                state.objectProxyEventNames = null;
            }
        }
    }

    
    private void analyzeIdentifierNode(IIdentifierNode node, AnalysisState state)
    {
        IDefinition def = node.resolve(project);
        if ((def == null) && !state.isObjectProxyExpression)
        {
            if (node.getName() == IASKeywordConstants.THIS)
                return;     // this is not "defensive programming"!
                        // we fully expect to get non-resolvable identifiers in some cases:
                        //      a) bad code. 
                        //      b) "this" 
                        // It should be fine to skip over these and continue without creating a watcher
        
                        // If, on the other hand, we are in an object proxy, then we
                        // may very well be a dynamic property with no definition,
                        // so will will continue on (with the knowledge that we have no
                        // IDefinition
            this.problems.add(new MXMLDatabindingSourceNotBindableProblem(node, node.getName()));
            return;
        }
        
        if (def instanceof IConstantDefinition)
        {
            return;     // we can ignore constants  - they can't be watched
        }
       
        assert state.chaining || state.curChain==null;      // we shouldn't have a chain if we aren't chaining
       
        // Now round up the arguments to make the watcher info
        List<String> eventNames = null;
        WatcherType type = WatcherType.ERROR;
        String name = null;
        Object id = null;
        
        if ((def == null) && state.isObjectProxyExpression)
        {
            // we are in a dynamic property situation... 
            type = WatcherType.PROPERTY;                // always use property watcher
            name = node.getName();                      // get the property name from the id node, since
                                                        // we have no definition
            id = node;                                  //use the parse node as identifier for the watcher, since
                                                        // we don't have an identifier to use. Not that this means we can't
                                                        // share dynamic property watchers. too bad!
            eventNames = state.objectProxyEventNames;   // use the event names we remembered from the proxy
        }
        else
        {
            // we are a not a dynamic property
            
            // Check to see if we are a cast. If so, we can ignore
            if (def instanceof IClassDefinition || def instanceof IInterfaceDefinition)
            {
                // we are an identifier that resolves to a class. perhaps we are a cast?
                // we are a case if the node parent is a function call, but in any case
                // if we see a class here it's either a cast, or it's just a class name
                // in an expression. 
                // If it's a cast, there's nothing wrong. If it's a class, we treat it like a constant string
                // bottom line: don't try to make a watcher, and don't generate a problem
                return;
            }
            
            type = determineWatcherType(def);  // figure out what kind of watcher to make
            if (type == WatcherType.ERROR)
            {
                System.err.println("can't get watcher for " + def);
                return;         // This should never happen. If it does, there is presumably a bug.
                                // But - better to recover here, than to go on and NPE.
                                // This is a workaround for CMP-1283
            }
            
            // if it's a function, make sure it is the one from the function call expression we are parsing
            // If it isn't, just return. This might happen if, for example, the function was
            // not bindable - then functionCallNameDefintion would be null.
            // I suspect there are other cases, too.
            if (type == WatcherType.FUNCTION)
            {
                if (def != state.functionCallNameDefintion)
                    return;
            }
            eventNames = WatcherInfoBase.getEventNamesFromDefinition(def, problems, node, project);
            name = def.getBaseName();
            id = def;
        }
        
        makeWatcherOfKnownType(id, type, state, node, eventNames, name, def);
        
        // Now, check if we need to make an XML watcher. These are special:
        //  We make an XMLWatcher and a property watcher to watch the same thing, so two of them
        // are created in this one call
        if (def instanceof IVariableDefinition)
        {
            // Is the def for an XML type variable?
            IVariableDefinition var = (IVariableDefinition)def;
            ITypeDefinition varType = var.resolveType(project);
            
            // note that varType might be null if code is bad
            boolean isVarXML = (varType==null) ? false : varType.isInstanceOf("XML", project);

            if (isVarXML)
            {
                // if XML,then create a watcher for it.
                String key = "XML";     // using this unique key will work, but it means we can never
                                        // share these. Which is OK.
                List<String> empty = Collections.emptyList();
                makeWatcherOfKnownType(key, WatcherType.XML, state, node, empty, name, null);
            }
        }
    }
    
    /**
     * Master "factory function" for Watcher Info
     * You should always use this factory, rather than instantiating the directly, as it is
     * easier and more reliable to user this function.
     * 
     * @param watcherKey is unique object "key" to refer to the created watcher. Often an IDefintion
     * @param type is which kind of watcher we want to create
     * @param state must be passed in so we can chain watchers as we create them during parse time
     * @param node the node that corresponds to the object we will be watching
     * @param eventNames the events that the watcher must listen to
     * @param name the name of the property or function that we will be watching
     * @param optionalDefinition the IDefinition for the node. Only required for Static Property Watchers
     */
    private void makeWatcherOfKnownType(
            Object watcherKey,
            WatcherType type,
            AnalysisState state,
            IASNode node,
            List<String> eventNames,
            String name,
            IDefinition optionalDefinition)
    {
        assert(eventNames != null);
        assert(name != null);
        
        WatcherInfoBase watcherInfo = bindingDataBase.getOrCreateWatcher(
                state.curChain,
                type,
                watcherKey,
                problems,
                node,
                eventNames);
  
        // After doing the "generic creation" we need to do some type specific
        // setup
        if (type == WatcherType.FUNCTION)
        {
            // TODO: couldn't we move this into a ctor somehow?
            FunctionWatcherInfo fwi = (FunctionWatcherInfo)watcherInfo;
           // fwi.setFunctionName(def.getName());
            fwi.setFunctionName(name);
            // Note: we might want to retrieve the function arguments in the future.
            // But they aren't available on this object - they are on the original FunctionCallExpression node
            FunctionCallNode fnNode = (FunctionCallNode)node.getAncestorOfType(FunctionCallNode.class);
            IExpressionNode[] paramNodes = fnNode.getArgumentNodes();
            fwi.params = paramNodes;
        }
        else if ((type == WatcherType.STATIC_PROPERTY) || (type == WatcherType.PROPERTY))
        {
            PropertyWatcherInfo pwi = (PropertyWatcherInfo)watcherInfo;
            pwi.setPropertyName(name);
            // TODO: can we just have a "name" on the base class??
        }
        else if (type == WatcherType.XML)
        {
            XMLWatcherInfo xwi = (XMLWatcherInfo)watcherInfo;
            xwi.setPropertyName(name);
        }
        
        if (type == WatcherType.STATIC_PROPERTY)
        {
            assert optionalDefinition != null;
            
            // static property watchers need this extra call
            StaticPropertyWatcherInfo pwi = (StaticPropertyWatcherInfo)watcherInfo;
            pwi.init(optionalDefinition, project);
        }
         
        watcherInfo.addBinding(bindingInfo);    // associate our binding with this watcher
                                                // note that one watcher can have more than one binding.
        if (state.chaining)
            state.curChain = watcherInfo;                 // mark this as the new bottom link in the chain   
    }
    
    private static  WatcherType determineWatcherType(IDefinition definition)
    {
        WatcherType ret = WatcherType.ERROR;
        
        if (definition == null) return ret; // there are "special" watchers where this will be null
        
        if (definition instanceof IVariableDefinition)
        {
            if (!definition.isStatic())
            {
                // we use regular property watchers on non-static variables
                ret = WatcherType.PROPERTY;
            }
            else
            {           
                ret = WatcherType.STATIC_PROPERTY;
            }
        }
        else if (definition instanceof IFunctionDefinition)
        {
            ret = WatcherType.FUNCTION;
        }
        else assert false;
        return ret;
    }
}
