package org.apache.commons.ognl;

/*
 * 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.
 */

import org.apache.commons.ognl.enhance.ExpressionCompiler;
import org.apache.commons.ognl.enhance.UnsupportedCompilationException;

import java.beans.IndexedPropertyDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Iterator;

/**
 * $Id$
 */
public class ASTProperty
    extends SimpleNode
    implements NodeType
{
    private boolean indexedAccess = false;

    private Class getterClass;

    private Class setterClass;

    public ASTProperty( int id )
    {
        super( id );
    }

    public void setIndexedAccess( boolean value )
    {
        indexedAccess = value;
    }

    /**
     * Returns true if this property is itself an index reference.
     *
     * @return Returns true if this property is itself an index reference.
     */
    public boolean isIndexedAccess()
    {
        return indexedAccess;
    }

    /**
     * Returns true if this property is described by an IndexedPropertyDescriptor and that if followed by an index
     * specifier it will call the index get/set methods rather than go through property accessors.
     *
     * @param context The context
     * @param source  The object source
     * @return true, if this property is described by an IndexedPropertyDescriptor
     * @throws OgnlException if an error occurs
     */
    public int getIndexedPropertyType( OgnlContext context, Object source )
        throws OgnlException
    {
        Class type = context.getCurrentType();
        Class prevType = context.getPreviousType();
        try
        {
            if ( !isIndexedAccess() )
            {
                Object property = getProperty( context, source );

                if ( property instanceof String )
                {
                    return OgnlRuntime.getIndexedPropertyType( context, ( source == null )
                        ? null
                        : OgnlRuntime.getCompiler( context ).getInterfaceClass( source.getClass() ),
                                                               (String) property );
                }
            }

            return OgnlRuntime.INDEXED_PROPERTY_NONE;
        }
        finally
        {
            context.setCurrentObject( source );
            context.setCurrentType( type );
            context.setPreviousType( prevType );
        }
    }

    public Object getProperty( OgnlContext context, Object source )
        throws OgnlException
    {
        return children[0].getValue( context, context.getRoot() );
    }

    protected Object getValueBody( OgnlContext context, Object source )
        throws OgnlException
    {
        Object property = getProperty( context, source );

        Object result = OgnlRuntime.getProperty( context, source, property );

        if ( result == null )
        {
            result =
                OgnlRuntime.getNullHandler( OgnlRuntime.getTargetClass( source ) ).nullPropertyValue( context, source,
                                                                                                      property );
        }

        return result;
    }

    protected void setValueBody( OgnlContext context, Object target, Object value )
        throws OgnlException
    {
        OgnlRuntime.setProperty( context, target, getProperty( context, target ), value );
    }

    public boolean isNodeSimpleProperty( OgnlContext context )
        throws OgnlException
    {
        return ( children != null ) && ( children.length == 1 ) && ( (SimpleNode) children[0] ).isConstant( context );
    }

    public Class getGetterClass()
    {
        return getterClass;
    }

    public Class getSetterClass()
    {
        return setterClass;
    }

    public String toGetSourceString( OgnlContext context, Object target )
    {
        if ( context.getCurrentObject() == null )
        {
            throw new UnsupportedCompilationException( "Current target is null." );
        }
        String result = "";
        Method m = null;

        try
        {
            /*
             * System.out.println("astproperty is indexed? : " + isIndexedAccess() + " child: " +
             * _children[0].getClass().getName() + " target: " + target.getClass().getName() + " current object: " +
             * context.getCurrentObject().getClass().getName());
             */

            Node child = children[0];
            if ( isIndexedAccess() )
            {
                Object value = child.getValue( context, context.getRoot() );

                if ( value == null || DynamicSubscript.class.isAssignableFrom( value.getClass() ) )
                {
                    throw new UnsupportedCompilationException(
                        "Value passed as indexed property was null or not supported." );
                }
                // Get root cast string if the child is a type that needs it (like a nested ASTProperty)

                String srcString = getSourceString( context, child );

                if ( context.get( "_indexedMethod" ) != null )
                {
                    m = (Method) context.remove( "_indexedMethod" );
                    getterClass = m.getReturnType();

                    Object indexedValue = OgnlRuntime.callMethod( context, target, m.getName(), new Object[]{ value } );

                    context.setCurrentType( getterClass );
                    context.setCurrentObject( indexedValue );
                    context.setCurrentAccessor(
                        OgnlRuntime.getCompiler( context ).getSuperOrInterfaceClass( m, m.getDeclaringClass() ) );

                    return "." + m.getName() + "(" + srcString + ")";
                }
                PropertyAccessor propertyAccessor = OgnlRuntime.getPropertyAccessor( target.getClass() );

                // System.out.println("child value : " + _children[0].getValue(context, context.getCurrentObject())
                // + " using propaccessor " + p.getClass().getName()
                // + " and srcString " + srcString + " on target: " + target);

                Object currentObject = context.getCurrentObject();
                if ( ASTConst.class.isInstance( child ) && Number.class.isInstance( currentObject ) )
                {
                    context.setCurrentType( OgnlRuntime.getPrimitiveWrapperClass( currentObject.getClass() ) );
                }
                Object indexValue = propertyAccessor.getProperty( context, target, value );
                result = propertyAccessor.getSourceAccessor( context, target, srcString );
                getterClass = context.getCurrentType();
                context.setCurrentObject( indexValue );

                return result;
            }

            String name = ( (ASTConst) child ).getValue().toString();

            target = getTarget( context, target, name );

            PropertyDescriptor pd = OgnlRuntime.getPropertyDescriptor( context.getCurrentObject().getClass(), name );

            if ( pd != null && pd.getReadMethod() != null && !context.getMemberAccess().isAccessible( context,
                                                                                                      context.getCurrentObject(),
                                                                                                      pd.getReadMethod(),
                                                                                                      name ) )
            {
                throw new UnsupportedCompilationException( "Member access forbidden for property " + name + " on class "
                                                               + context.getCurrentObject().getClass() );
            }

            if ( this.getIndexedPropertyType( context, context.getCurrentObject() ) > 0 && pd != null )
            {
                // if an indexed method accessor need to use special property descriptors to find methods

                if ( pd instanceof IndexedPropertyDescriptor )
                {
                    m = ( (IndexedPropertyDescriptor) pd ).getIndexedReadMethod();
                }
                else
                {
                    if ( !(pd instanceof ObjectIndexedPropertyDescriptor) ) {
                        throw new OgnlException( "property '" + name + "' is not an indexed property" );
                    }
                    m = ( (ObjectIndexedPropertyDescriptor) pd ).getIndexedReadMethod();
                }

                if ( parent == null )
                {
                    // the above pd will be the wrong result sometimes, such as methods like getValue(int) vs String[]
                    // getValue()
                    m = OgnlRuntime.getReadMethod( context.getCurrentObject().getClass(), name );

                    result = m.getName() + "()";
                    getterClass = m.getReturnType();
                }
                else
                {
                    context.put( "_indexedMethod", m );
                }
            }
            else
            {

                /*
                 * System.out.println("astproperty trying to get " + name + " on object target: " +
                 * context.getCurrentObject().getClass().getName() + " current type " + context.getCurrentType() +
                 * " current accessor " + context.getCurrentAccessor() + " prev type " + context.getPreviousType() +
                 * " prev accessor " + context.getPreviousAccessor());
                 */

                PropertyAccessor pa = OgnlRuntime.getPropertyAccessor( context.getCurrentObject().getClass() );

                if ( context.getCurrentObject().getClass().isArray() )
                {
                    if ( pd == null )
                    {
                        pd = OgnlRuntime.getProperty( context.getCurrentObject().getClass(), name );

                        if ( pd != null && pd.getReadMethod() != null )
                        {
                            m = pd.getReadMethod();
                            result = pd.getName();
                        }
                        else
                        {
                            getterClass = int.class;
                            context.setCurrentAccessor( context.getCurrentObject().getClass() );
                            context.setCurrentType( int.class );
                            result = "." + name;
                        }
                    }
                }
                else
                {
                    if ( pd != null && pd.getReadMethod() != null )
                    {
                        m = pd.getReadMethod();
                        result = "." + m.getName() + "()";
                    }
                    else if ( pa != null )
                    {
                        Object currObj = context.getCurrentObject();
                        Class currType = context.getCurrentType();
                        Class prevType = context.getPreviousType();

                        String srcString = child.toGetSourceString( context, context.getRoot() );

                        if ( ASTConst.class.isInstance( child ) && String.class.isInstance(
                            context.getCurrentObject() ) )
                        {
                            srcString = "\"" + srcString + "\"";
                        }
                        context.setCurrentObject( currObj );
                        context.setCurrentType( currType );
                        context.setPreviousType( prevType );

                        result = pa.getSourceAccessor( context, context.getCurrentObject(), srcString );

                        getterClass = context.getCurrentType();
                    }
                }
            }

        }
        catch ( Throwable t )
        {
            throw OgnlOps.castToRuntime( t );
        }

        // set known property types for NodeType interface when possible

        if ( m != null )
        {
            getterClass = m.getReturnType();

            context.setCurrentType( m.getReturnType() );
            context.setCurrentAccessor(
                OgnlRuntime.getCompiler( context ).getSuperOrInterfaceClass( m, m.getDeclaringClass() ) );
        }

        context.setCurrentObject( target );

        return result;
    }

    Object getTarget( OgnlContext context, Object target, String name )
        throws OgnlException
    {
        Class<?> clazz = context.getCurrentObject().getClass();
        if ( !Iterator.class.isAssignableFrom( clazz ) || ( Iterator.class.isAssignableFrom( clazz ) && !name.contains(
            "next" ) ) )
        {
            Object currObj = target;

            try
            {
                target = getValue( context, context.getCurrentObject() );
            }
            catch ( NoSuchPropertyException e )
            {
                try
                {
                    target = getValue( context, context.getRoot() );
                }
                catch ( NoSuchPropertyException ex )
                {
                    // ignore
                }
            }
            finally
            {
                context.setCurrentObject( currObj );
            }
        }
        return target;
    }

    Method getIndexedWriteMethod( PropertyDescriptor pd )
    {
        if ( IndexedPropertyDescriptor.class.isInstance( pd ) )
        {
            return ( (IndexedPropertyDescriptor) pd ).getIndexedWriteMethod();
        }
        if ( ObjectIndexedPropertyDescriptor.class.isInstance( pd ) )
        {
            return ( (ObjectIndexedPropertyDescriptor) pd ).getIndexedWriteMethod();
        }

        return null;
    }

    public String toSetSourceString( OgnlContext context, Object target )
    {
        String result = "";
        Method m = null;

        if ( context.getCurrentObject() == null )
        {
            throw new UnsupportedCompilationException( "Current target is null." );
        }
        /*
         * System.out.println("astproperty(setter) is indexed? : " + isIndexedAccess() + " child: " +
         * _children[0].getClass().getName() + " target: " + target.getClass().getName() + " children length: " +
         * _children.length);
         */

        try
        {

            Node child = children[0];
            if ( isIndexedAccess() )
            {
                Object value = child.getValue( context, context.getRoot() );

                if ( value == null )
                {
                    throw new UnsupportedCompilationException(
                        "Value passed as indexed property is null, can't enhance statement to bytecode." );
                }

                String srcString = getSourceString( context, child );

                // System.out.println("astproperty setter using indexed value " + value + " and srcString: " +
                // srcString);

                if ( context.get( "_indexedMethod" ) == null ) {
                    PropertyAccessor propertyAccessor = OgnlRuntime.getPropertyAccessor( target.getClass() );

                    Object currentObject = context.getCurrentObject();
                    if ( ASTConst.class.isInstance( child ) && Number.class.isInstance( currentObject ) )
                    {
                        context.setCurrentType( OgnlRuntime.getPrimitiveWrapperClass( currentObject.getClass() ) );
                    }
                    Object indexValue = propertyAccessor.getProperty( context, target, value );
                    result = lastChild( context )
                        ? propertyAccessor.getSourceSetter( context, target, srcString )
                        : propertyAccessor.getSourceAccessor( context, target, srcString );

                    /*
                     * System.out.println("ASTProperty using propertyaccessor and isLastChild? " + lastChild(context) +
                     * " generated source of: " + result + " using accessor class: " + p.getClass().getName());
                     */

                    // result = p.getSourceAccessor(context, target, srcString);
                    getterClass = context.getCurrentType();
                    context.setCurrentObject( indexValue );

                    /*
                     * PropertyAccessor p = OgnlRuntime.getPropertyAccessor(target.getClass()); if
                     * (ASTConst.class.isInstance(_children[0]) && Number.class.isInstance(context.getCurrentObject()))
                     * {
                     * context.setCurrentType(OgnlRuntime.getPrimitiveWrapperClass(context.getCurrentObject().getClass(
                     * ))); } result = p.getSourceSetter(context, target, srcString); context.setCurrentObject(value);
                     * context.setCurrentType(getterClass);
                     */
                    return result;
                }
                m = (Method) context.remove( "_indexedMethod" );
                PropertyDescriptor pd = (PropertyDescriptor) context.remove( "_indexedDescriptor" );

                boolean lastChild = lastChild( context );
                if ( lastChild )
                {
                    m = getIndexedWriteMethod( pd );

                    if ( m == null )
                    {
                        throw new UnsupportedCompilationException(
                            "Indexed property has no corresponding write method." );
                    }
                }

                setterClass = m.getParameterTypes()[0];

                Object indexedValue = null;
                if ( !lastChild )
                {
                    indexedValue = OgnlRuntime.callMethod( context, target, m.getName(), new Object[]{ value } );
                }
                context.setCurrentType( setterClass );
                context.setCurrentAccessor(
                    OgnlRuntime.getCompiler( context ).getSuperOrInterfaceClass( m, m.getDeclaringClass() ) );

                if ( !lastChild )
                {
                    context.setCurrentObject( indexedValue );
                    return "." + m.getName() + "(" + srcString + ")";
                }
                return "." + m.getName() + "(" + srcString + ", $3)";
            }

            String name = ( (ASTConst) child ).getValue().toString();

            // System.out.println(" astprop(setter) : trying to set " + name + " on object target " +
            // context.getCurrentObject().getClass().getName());

            target = getTarget( context, target, name );

            PropertyDescriptor pd = OgnlRuntime.getPropertyDescriptor(
                OgnlRuntime.getCompiler( context ).getInterfaceClass( context.getCurrentObject().getClass() ), name );

            if ( pd != null )
            {
                Method pdMethod = lastChild( context ) ? pd.getWriteMethod() : pd.getReadMethod();

                if ( pdMethod != null && !context.getMemberAccess().isAccessible( context, context.getCurrentObject(),
                                                                                  pdMethod, name ) )
                {
                    throw new UnsupportedCompilationException(
                        "Member access forbidden for property " + name + " on class "
                            + context.getCurrentObject().getClass() );
                }
            }

            if ( pd != null && this.getIndexedPropertyType( context, context.getCurrentObject() ) > 0 )
            {
                // if an indexed method accessor need to use special property descriptors to find methods

                if ( pd instanceof IndexedPropertyDescriptor )
                {
                    IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
                    m = lastChild( context ) ? ipd.getIndexedWriteMethod() : ipd.getIndexedReadMethod();
                }
                else
                {
                    if ( !(pd instanceof ObjectIndexedPropertyDescriptor) ) {
                        throw new OgnlException( "property '" + name + "' is not an indexed property" );
                    }
                    ObjectIndexedPropertyDescriptor opd = (ObjectIndexedPropertyDescriptor) pd;

                    m = lastChild( context ) ? opd.getIndexedWriteMethod() : opd.getIndexedReadMethod();
                }

                if ( parent == null )
                {
                    // the above pd will be the wrong result sometimes, such as methods like getValue(int) vs String[]
                    // getValue()

                    m = OgnlRuntime.getWriteMethod( context.getCurrentObject().getClass(), name );
                    Class parm = m.getParameterTypes()[0];
                    String cast = parm.isArray() ? ExpressionCompiler.getCastString( parm ) : parm.getName();

                    result = m.getName() + "((" + cast + ")$3)";
                    setterClass = parm;
                }
                else
                {
                    context.put( "_indexedMethod", m );
                    context.put( "_indexedDescriptor", pd );
                }

            }
            else
            {
                PropertyAccessor pa = OgnlRuntime.getPropertyAccessor( context.getCurrentObject().getClass() );

                /*
                 * System.out.println("astproperty trying to set " + name + " on object target: " +
                 * context.getCurrentObject().getClass().getName() + " using propertyaccessor type: " + pa);
                 */

                if ( target != null )
                {
                    setterClass = target.getClass();
                }
                if ( parent != null && pd != null && pa == null )
                {
                    m = pd.getReadMethod();
                    result = m.getName() + "()";
                }
                else
                {
                    if ( context.getCurrentObject().getClass().isArray() )
                    {
                        result = "";
                    }
                    else if ( pa != null )
                    {
                        Object currObj = context.getCurrentObject();
                        // Class currType = context.getCurrentType();
                        // Class prevType = context.getPreviousType();

                        String srcString = child.toGetSourceString( context, context.getRoot() );

                        if ( ASTConst.class.isInstance( child ) && String.class.isInstance(
                            context.getCurrentObject() ) )
                        {
                            srcString = "\"" + srcString + "\"";
                        }

                        context.setCurrentObject( currObj );
                        // context.setCurrentType(currType);
                        // context.setPreviousType(prevType);

                        if ( !lastChild( context ) )
                        {
                            result = pa.getSourceAccessor( context, context.getCurrentObject(), srcString );
                        }
                        else
                        {
                            result = pa.getSourceSetter( context, context.getCurrentObject(), srcString );
                        }

                        getterClass = context.getCurrentType();
                    }
                }
            }

        }
        catch ( Throwable t )
        {
            throw OgnlOps.castToRuntime( t );
        }

        context.setCurrentObject( target );

        if ( m != null )
        {
            context.setCurrentType( m.getReturnType() );
            context.setCurrentAccessor(
                OgnlRuntime.getCompiler( context ).getSuperOrInterfaceClass( m, m.getDeclaringClass() ) );
        }

        return result;
    }

    public <R, P> R accept( NodeVisitor<? extends R, ? super P> visitor, P data )
        throws OgnlException
    {
        return visitor.visit( this, data );
    }

    private static String getSourceString( OgnlContext context, Node child )
    {
        String srcString = child.toGetSourceString( context, context.getRoot() );
        srcString = ExpressionCompiler.getRootExpression( child, context.getRoot(), context ) + srcString;

        if ( ASTChain.class.isInstance( child ) )
        {
            String cast = (String) context.remove( ExpressionCompiler.PRE_CAST );
            if ( cast != null )
            {
                srcString = cast + srcString;
            }
        }

        if ( ASTConst.class.isInstance( child ) && String.class.isInstance( context.getCurrentObject() ) )
        {
            srcString = "\"" + srcString + "\"";
        }
        // System.out.println("indexed getting with child srcString: " + srcString + " value class: " +
        // value.getClass() + " and child: " + _children[0].getClass());
        return srcString;
    }

}
