/*
 *  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.directory.studio.ldapbrowser.core.model;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.ObjectClass;
import org.apache.directory.api.util.Strings;
import org.apache.directory.studio.ldapbrowser.core.model.schema.Schema;
import org.apache.directory.studio.ldapbrowser.core.model.schema.SchemaUtils;


/**
 * This class implements an attribute description as 
 * specified in RFC4512, section 2.5:
 * 
 *    An attribute description is represented by the ABNF:
 *
 *      attributedescription = attributetype options
 *      attributetype = oid
 *      options = *( SEMI option )
 *      option = 1*keychar
 *
 *   where &lt;attributetype> identifies the attribute type and each <option>
 *   identifies an attribute option.  Both &lt;attributetype> and <option>
 *   productions are case insensitive.  The order in which <option>s
 *   appear is irrelevant.  That is, any two &lt;attributedescription>s that
 *   consist of the same &lt;attributetype> and same set of <option>s are
 *   equivalent.
 *
 *   Examples of valid attribute descriptions:
 *
 *      2.5.4.0
 *      cn;lang-de;lang-en
 *      owner
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class AttributeDescription implements Serializable
{

    private static final long serialVersionUID = 1L;

    /** The user provided description. */
    private String description;

    /** The parsed attribute type. */
    private String parsedAttributeType;

    /** The parsed language tag option list. */
    private List<String> parsedLangList;

    /** The parsed option list, except the language tags. */
    private List<String> parsedOptionList;


    /**
     * Creates a new instance of AttributeDescription.
     * 
     * @param description the user provided description
     */
    public AttributeDescription( String description )
    {
        this.description = description;

        String[] attributeDescriptionComponents = description.split( IAttribute.OPTION_DELIMITER );
        this.parsedAttributeType = attributeDescriptionComponents[0];
        this.parsedLangList = new ArrayList<String>();
        this.parsedOptionList = new ArrayList<String>();
        for ( int i = 1; i < attributeDescriptionComponents.length; i++ )
        {
            String component = attributeDescriptionComponents[i];
            if ( component.startsWith( IAttribute.OPTION_LANG_PREFIX ) )
            {
                this.parsedLangList.add( component );
            }
            else
            {
                this.parsedOptionList.add( component );
            }
        }
    }


    /**
     * Gets the user provided description.
     * 
     * @return the user provided description
     */
    public String getDescription()
    {
        return description;
    }


    /**
     * Gets the parsed attribute type.
     * 
     * @return the parsed attribute type
     */
    public String getParsedAttributeType()
    {
        return parsedAttributeType;
    }


    /**
     * Gets the list of parsed language tags.
     * 
     * @return the list of parsed language tags
     */
    public List<String> getParsedLangList()
    {
        return parsedLangList;
    }


    /**
     * Gets the list of parsed options, except the language tags.
     * 
     * @return the list of parsed options, except the language tags
     */
    public List<String> getParsedOptionList()
    {
        return parsedOptionList;
    }


    /**
     * Returns the attribute description with the numeric OID
     * instead of the descriptive attribute type.
     * 
     * @param schema the schema
     * 
     * @return the attribute description with the numeric OID
     */
    public String toOidString( Schema schema )
    {
        if ( schema == null )
        {
            return description;
        }

        AttributeType atd = schema.getAttributeTypeDescription( parsedAttributeType );
        String oidString = atd.getOid();

        if ( !parsedLangList.isEmpty() )
        {
            for ( Iterator<String> it = parsedLangList.iterator(); it.hasNext(); )
            {
                String element = it.next();
                oidString += element;

                if ( it.hasNext() || !parsedOptionList.isEmpty() )
                {
                    oidString += IAttribute.OPTION_DELIMITER;
                }
            }
        }
        if ( !parsedOptionList.isEmpty() )
        {
            for ( Iterator<String> it = parsedOptionList.iterator(); it.hasNext(); )
            {
                String element = it.next();
                oidString += element;

                if ( it.hasNext() )
                {
                    oidString += IAttribute.OPTION_DELIMITER;
                }
            }
        }

        return oidString;
    }


    /**
     * Checks if the given attribute description is subtype of 
     * this attribute description.
     * 
     * @param other the other attribute description
     * @param schema the schema
     * 
     * @return true, if the other attribute description is a 
     *         subtype of this attribute description.
     */
    public boolean isSubtypeOf( AttributeDescription other, Schema schema )
    {
        // this=name, other=givenName;lang-de -> false
        // this=name;lang-en, other=givenName;lang-de -> false
        // this=givenName, other=name -> true
        // this=givenName;lang-de, other=givenName -> true
        // this=givenName;lang-de, other=name -> true
        // this=givenName;lang-en, other=name;lang-de -> false
        // this=givenName, other=givenName;lang-de -> false

        // check equal descriptions
        if ( this.toOidString( schema ).equals( other.toOidString( schema ) ) )
        {
            return false;
        }

        AttributeType myAtd = schema.getAttributeTypeDescription( this.getParsedAttributeType() );
        AttributeType otherAtd = schema.getAttributeTypeDescription( other.getParsedAttributeType() );

        // special case *: all user attributes (RFC4511)
        if ( SchemaConstants.ALL_USER_ATTRIBUTES.equals( other.description ) && !SchemaUtils.isOperational( myAtd ) )
        {
            return true;
        }

        // special case +: all operational attributes (RFC3673)
        if ( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES.equals( other.description )
            && SchemaUtils.isOperational( myAtd ) )
        {
            return true;
        }

        // special case @: attributes by object class (RFC4529)
        if ( other.description.length() > 1 && other.description.startsWith( "@" ) ) //$NON-NLS-1$
        {
            String objectClass = other.description.substring( 1 );
            ObjectClass ocd = schema.getObjectClassDescription( objectClass );
            ocd.getMayAttributeTypes();
            ocd.getMustAttributeTypes();

            Collection<String> names = new HashSet<String>();
            names.addAll( SchemaUtils.getMayAttributeTypeDescriptionNamesTransitive( ocd, schema ) );
            names.addAll( SchemaUtils.getMustAttributeTypeDescriptionNamesTransitive( ocd, schema ) );
            for ( String name : names )
            {
                AttributeType atd = schema.getAttributeTypeDescription( name );
                if ( myAtd == atd )
                {
                    return true;
                }
            }
        }

        // check type
        if ( myAtd != otherAtd )
        {
            AttributeType superiorAtd = null;
            String superiorName = myAtd.getSuperiorOid();
            while ( superiorName != null )
            {
                superiorAtd = schema.getAttributeTypeDescription( superiorName );
                if ( superiorAtd == otherAtd )
                {
                    break;
                }
                superiorName = superiorAtd.getSuperiorOid();
            }
            if ( superiorAtd != otherAtd )
            {
                return false;
            }
        }

        // check options
        List<String> myOptionsList = new ArrayList<String>( this.getParsedOptionList() );
        List<String> otherOptionsList = new ArrayList<String>( other.getParsedOptionList() );
        otherOptionsList.removeAll( myOptionsList );
        if ( !otherOptionsList.isEmpty() )
        {
            return false;
        }

        // check language tags
        List<String> myLangList = new ArrayList<String>( this.getParsedLangList() );
        List<String> otherLangList = new ArrayList<String>( other.getParsedLangList() );
        for ( String myLang : myLangList )
        {
            for ( Iterator<String> otherIt = otherLangList.iterator(); otherIt.hasNext(); )
            {
                String otherLang = otherIt.next();
                if ( otherLang.endsWith( "-" ) ) //$NON-NLS-1$
                {
                    if ( Strings.toLowerCase( myLang ).startsWith( Strings.toLowerCase( otherLang ) ) )
                    {
                        otherIt.remove();
                    }
                }
                else
                {
                    if ( myLang.equalsIgnoreCase( otherLang ) )
                    {
                        otherIt.remove();
                    }
                }
            }
        }
        if ( !otherLangList.isEmpty() )
        {
            return false;
        }

        return true;
    }

}
