/*
 * 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.netbeans.modules.javascript2.model;

import org.netbeans.modules.javascript2.model.api.Occurrence;
import org.netbeans.modules.javascript2.model.api.ModelUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;
import org.netbeans.modules.csl.api.Documentation;
import org.netbeans.modules.csl.api.Modifier;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.javascript2.doc.spi.JsDocumentationHolder;
import org.netbeans.modules.javascript2.model.api.JsElement;
import org.netbeans.modules.javascript2.model.api.JsFunction;
import org.netbeans.modules.javascript2.model.api.JsObject;
import org.netbeans.modules.javascript2.model.api.Occurrence;
import org.netbeans.modules.javascript2.types.api.DeclarationScope;
import org.netbeans.modules.javascript2.types.api.Identifier;
import org.netbeans.modules.javascript2.types.api.Type;
import org.netbeans.modules.javascript2.types.api.TypeUsage;

/**
 *
 * @author Petr Pisl
 */
public class JsObjectImpl extends JsElementImpl implements JsObject {

//    final protected HashMap<String, JsObject> properties = new HashMap<String, JsObject>();
    final protected LinkedHashMap<String, JsObject> properties = new LinkedHashMap<String, JsObject>();
    private Identifier declarationName;
    private JsObject parent;
    final private List<Occurrence> occurrences = new ArrayList<Occurrence>();
    final private NavigableMap<Integer, Collection<TypeUsage>> assignments = new TreeMap<>();
    final private Map<String, Integer>assignmentsReverse = new HashMap<>();
    private int countOfAssignments = 0;
    private boolean hasName;
    private Documentation documentation;
    protected JsElement.Kind kind;
    private boolean isVirtual;
    private boolean isAnonymous;

    public JsObjectImpl(JsObject parent, Identifier name, OffsetRange offsetRange,
            String mimeType, String sourceLabel) {
        super((parent != null ? parent.getFileObject() : null), name.getName(),
                ModelUtils.PROTOTYPE.equals(name.getName()), offsetRange, EnumSet.of(Modifier.PUBLIC), mimeType, sourceLabel);
        this.declarationName = name;
        this.parent = parent;
        this.hasName = name.getOffsetRange().getStart() != name.getOffsetRange().getEnd();
        this.kind = null;
        this.isVirtual = false;
        this.isAnonymous = false;
    }

    public JsObjectImpl(JsObject parent, Identifier name, OffsetRange offsetRange,
            boolean isDeclared, Set<Modifier> modifiers, String mimeType, String sourceLabel) {
        super((parent != null ? parent.getFileObject() : null), name.getName(),
                isDeclared, offsetRange, modifiers, mimeType, sourceLabel);
        this.declarationName = name;
        this.parent = parent;
        this.hasName = !OffsetRange.NONE.equals(name.getOffsetRange()) && (name.getOffsetRange().getStart() != name.getOffsetRange().getEnd());
        this.kind = null;
        this.isVirtual = false;
    }

    public JsObjectImpl(JsObject parent, Identifier name, OffsetRange offsetRange,
            boolean isDeclared, String mimeType, String sourceLabel) {
        this(parent, name, offsetRange, isDeclared, EnumSet.of(Modifier.PUBLIC), mimeType, sourceLabel);
    }

    protected JsObjectImpl(JsObject parent, String name, boolean isDeclared,
            OffsetRange offsetRange, Set<Modifier> modifiers, String mimeType, String sourceLabel) {
        super((parent != null ? parent.getFileObject() : null), name, isDeclared,
                offsetRange, modifiers, mimeType, sourceLabel);
        this.declarationName = null;
        this.parent = parent;
        this.hasName = false;
    }

    @Override
    public Identifier getDeclarationName() {
        return declarationName;
    }

    @Override
    public String getName() {
        return declarationName != null ? declarationName.getName() : super.getName();
    }
    
    public void setDeclarationName(Identifier declaration) {
        declarationName = declaration;
        hasName = declaration.getOffsetRange().getLength() > 0;
    }

    @Override
    public Kind getJSKind() {
        if (kind != null) {
            return kind;
        }
        if (parent == null) {
            // global object
            return Kind.FILE;
        }
        if (ModelUtils.PROTOTYPE.equals(getName())) {
            return Kind.OBJECT;
        }
        if (isDeclared()) {
            if (ModelUtils.ARGUMENTS.equals(getName())) {
                // special variable object of every function
                return Kind.VARIABLE;
            }
            if (!getAssignmentForOffset(getDeclarationName().getOffsetRange().getEnd()).isEmpty()
                    && hasOnlyVirtualProperties()) {
                if (getParent().getParent() == null || getModifiers().contains(Modifier.PRIVATE)) {
                    return Kind.VARIABLE;
                } else {
                    return Kind.PROPERTY;
                }
            }
        } else {
            if (!getProperties().isEmpty()) {
                return Kind.OBJECT;
            }
        }
        if (getProperties().isEmpty()) {
            if (getParent().isAnonymous() && (getParent() instanceof AnonymousObject)) {
                return Kind.PROPERTY;
            }
            if (getParent().getParent() == null || getModifiers().contains(Modifier.PRIVATE)) {
                // variable or the global object
                return Kind.VARIABLE;
            }
            if (getParent() instanceof JsFunction) {
                if (isDeclared()) {
                    return getModifiers().contains(Modifier.PRIVATE) ? Kind.VARIABLE : Kind.PROPERTY;
                }
            }
            return Kind.PROPERTY;
        }
        return Kind.OBJECT;
    }

    private boolean hasOnlyVirtualProperties() {
        for (JsObject property : getProperties().values()) {
            if (property.isDeclared() || ModelUtils.PROTOTYPE.equals(property.getName())) {
                return false;
            }
        }
        return true;
    }

    @Override
    public Map<String, ? extends JsObject> getProperties() {
        return properties;
    }

    @Override
    public void addProperty(String name, JsObject property) {
        properties.put(name, property);
    }

    @Override
    public JsObject getProperty(String name) {
        return properties.get(name);
    }

    @Override
    public JsObject getParent() {
        return parent;
    }

    public void setParent(JsObject newParent) {
        this.parent = newParent;
    }

    @Override
    public boolean isVirtual() {
        return isVirtual;
    }

    public void setVirtual(boolean isVirtual) {
        this.isVirtual = isVirtual;
    }

    @Override
    public int getOffset() {
        return declarationName == null ? -1 : declarationName.getOffsetRange().getStart();
    }

    @Override
    public List<Occurrence> getOccurrences() {
        return occurrences;
    }

    @Override
    public void addOccurrence(OffsetRange offsetRange) {
//        boolean isThere = false;
//        for (Occurrence occurrence : occurrences) {
//            if (occurrence.getOffsetRange().equals(offsetRange)) {
//                isThere = true;
//                break;
//            }
//        }
//        if (!isThere) {
//            occurrences.add(new OccurrenceImpl(offsetRange, this));
//        }
        Occurrence occurrence = new Occurrence(offsetRange, this);
        if (!occurrences.contains(occurrence)) {
            occurrences.add(occurrence);
        }
    }

    public void addAssignment(Collection<TypeUsage> typeNames, int offset) {
        for(TypeUsage type: typeNames) {
            addAssignment(type, offset);
        }
    }

    @Override
    public void clearAssignments() {
        assignments.clear();
    }

    @Override
    public void addAssignment(TypeUsage typeName, int offset) {
        if (typeName == null || (Type.UNDEFINED.equals(typeName.getType()) && assignments.size() > 0)) {
            // don't add undefined type, if there are already some types
            return;
        }
        Collection<TypeUsage> types = assignments.get(offset);
        if (types == null) {
            // create always empty list, need to be counted for number of assignments.
            types = new ArrayList<TypeUsage>();
            assignments.put(offset, types);
        }
        
        Integer alreadyDefinedOffset = assignmentsReverse.get(typeName.getType());
        if (alreadyDefinedOffset != null) {
            // there is already assignment of this type. It's enough to store the
            // assignment with the min offset
            if(alreadyDefinedOffset <= offset) {
                // do nothing, just remember the previous one
                return;
            } else {
                // we need to replace the assignment with bigger offset
                Collection<TypeUsage> typesToRemove = assignments.get(alreadyDefinedOffset);
                for (TypeUsage type : typesToRemove) {
                    if (type.getType().equals(typeName.getType())) {
                        typesToRemove.remove(type);
                        break;
                    }
                }
            }
        }
        assignmentsReverse.put(typeName.getType(), offset);
        types.add(typeName);
    }

    @Override
    public Collection<? extends TypeUsage> getAssignmentForOffset(int offset) {
        List<? extends TypeUsage> result = new ArrayList<>();
        Map.Entry<Integer, Collection<TypeUsage>> found = assignments.floorEntry(offset);
        int tmpOffset = offset;
        while (found != null) {
            result.addAll((Collection)found.getValue());
            tmpOffset = found.getKey() - 1;
            found = assignments.floorEntry(tmpOffset);
        }
//        if (result.isEmpty()) {
//            Collection<TypeUsage> resolved = new HashSet();
//            for(TypeUsage item : result) {
//                TypeUsage type = (TypeUsage)item;
//                if (type.isResolved()) {
//                    resolved.add(type);
//                } else {
//                    JsObject jsObject = ModelUtils.findJsObjectByName(ModelUtils.getGlobalObject(this), type.getType());
//                    if(jsObject != null) {
//                        resolved.addAll(resolveAssignments(jsObject, offset));
//                    }
//                }
//            }
//            if(resolved.isEmpty()) {
//                // keep somthink in the assignments. 
//                resolved.add(new TypeUsage("Object", offset, true));
//            }
//            Collection<TypeUsage> resolved = new HashSet();
//            //resolved.add(new TypeUsage("Object", offset, true));
//            result = resolved;
//        }

        return result;
    }

    public int getAssignmentCount() {
        return assignments.size();
    }

    @Override
    public Collection<? extends TypeUsage> getAssignments() {
        List<TypeUsage> values;
        values = new ArrayList<TypeUsage>();
        for (Collection<? extends TypeUsage> types : assignments.values()) {
            values.addAll(types);
        }
        return Collections.unmodifiableCollection(values);
    }

    @Override
    public String getFullyQualifiedName() {
        if (getParent() == null) {
            return getName();
        }
        StringBuilder result = new StringBuilder();
        JsObject pObject = this;
        result.append(getName());

        while ((pObject = pObject.getParent()).getParent() != null) {
            result.insert(0, ".");
            result.insert(0, pObject.getName());
        }
        return result.toString();
    }

    @Override
    public boolean isAnonymous() {
        return isAnonymous;
    }

    @Override
    public void setAnonymous(boolean value) {
        this.isAnonymous = value;
    }

    @Override
    public boolean containsOffset(int offset) {
        if (getOffsetRange().containsInclusive(offset)) {
            return true;
        }
        // some methods can be declared outside the main object
        for (JsObject property : getProperties().values()) {
            if (property.getOffsetRange().containsInclusive(offset)) {
                return true;
            }
            if (ModelUtils.PROTOTYPE.equals(property.getName())) {
                if (property.containsOffset(offset)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean hasExactName() {
        return hasName;
    }

    public final void setJsKind(JsElement.Kind kind) {
        this.kind = kind;
    }

    protected Collection<TypeUsage> resolveAssignments(JsObject jsObject, int offset) {
        Collection<String> visited = new HashSet<>();  // for preventing infinited loops
        return resolveAssignments(jsObject, offset, visited);
    }

    protected Collection<TypeUsage> resolveAssignments(JsObject jsObject, int offset, Collection<String> visited) {
        Collection<TypeUsage> result = new HashSet<>();
        String fqn = jsObject.getFullyQualifiedName();
        if (visited.contains(fqn)) {
            return result;
        }
        visited.add(fqn);
        Collection<? extends TypeUsage> offsetAssignments = Collections.emptyList();
        Map.Entry<Integer, Collection<TypeUsage>> found = ((JsObjectImpl) jsObject).assignments.floorEntry(offset);
        if (found != null) {
            offsetAssignments = found.getValue();
        }
        if (offsetAssignments.isEmpty() && !jsObject.getProperties().isEmpty()) {
            result.add(new TypeUsage(jsObject.getFullyQualifiedName(), jsObject.getOffset(), true));
        } else {
            for (TypeUsage assignment : offsetAssignments) {
                if (!visited.contains(assignment.getType())) {
                    if (assignment.isResolved()) {
                        result.add(assignment);
                    } else {
                        if (assignment.getType().startsWith("@")) {
                            result.addAll(ModelUtils.resolveTypeFromSemiType(jsObject, assignment));
                        } else {
                            DeclarationScope scope = ModelUtils.getDeclarationScope(jsObject);
                            JsObject object = ModelUtils.getJsObjectByName(scope, assignment.getType());
                            if (object == null) {
                                JsObject gloal = ModelUtils.getGlobalObject(jsObject);
                                object = ModelUtils.findJsObjectByName(gloal, assignment.getType());
                            }
                            if (object != null) {
                                Collection<TypeUsage> resolvedFromObject = resolveAssignments(object, found != null ? found.getKey() : -1, visited);
                                if (resolvedFromObject.isEmpty()) {
                                    result.add(new TypeUsage(object.getFullyQualifiedName(), assignment.getOffset(), true));
                                } else {
                                    result.addAll(resolvedFromObject);
                                }
                            }
                        }
                    }
                }
            }
        }
        return result;
    }

    public void resolveTypes(JsDocumentationHolder jsDocHolder) {
        if (parent == null 
                || (parent != null && parent.getOffset() == getOffset() && ModelUtils.ARGUMENTS.equals(getName())) ) {
            return;
        }
        Collection<TypeUsage> resolved = new ArrayList<>();
        for (Collection<TypeUsage> unresolved : assignments.values()) {
            resolved.clear();
            JsObject global = ModelUtils.getGlobalObject(parent);
            for (TypeUsage type : unresolved) {
                Collection<TypeUsage> resolvedHere = new ArrayList<TypeUsage>();
                if (!type.isResolved()) {
                    resolvedHere.addAll(ModelUtils.resolveTypeFromSemiType(this, type));
                } else {
                    resolvedHere.add(type);
                }
                if (!type.getType().contains(ModelUtils.THIS)) {
                    for (TypeUsage typeHere : resolvedHere) {
                        if (typeHere.getOffset() > 0) {
                            TypeUsage newType = typeHere;
                            if (!typeHere.isResolved() && (typeHere.getType().startsWith(SemiTypeResolverVisitor.ST_PRO))) {
                                newType = ModelUtils.createResolvedType(global, typeHere);
                            }
                            String rType = ModelUtils.getFQNFromType(newType);
                            JsObject jsObject = ModelUtils.findJsObjectByName(global, rType);
                            
                            if (jsObject == null && rType.indexOf('.') == -1 && global instanceof DeclarationScope) {
                                DeclarationScope declarationScope = ModelUtils.getDeclarationScope((DeclarationScope) global, typeHere.getOffset());
                                jsObject = ModelUtils.getJsObjectByName(declarationScope, rType);
                                if (jsObject == null) {
                                    JsObject decParent = (this.parent.getJSKind() != JsElement.Kind.ANONYMOUS_OBJECT
                                            && this.parent.getJSKind() != JsElement.Kind.OBJECT_LITERAL)
                                            ? this.parent : this.parent.getParent();
                                    while (jsObject == null && decParent != null) {
                                        jsObject = decParent.getProperty(rType);
                                        decParent = decParent.getParent();
                                    }
                                }
                            }
                            if (jsObject != null) {
//                                if (typeHere.isResolved() && !jsObject.isAnonymous()) {
                                if (typeHere.isResolved()) {
                                    int index = rType.lastIndexOf('.');
                                    int typeLength = (index > -1) ? rType.length() - index - 1 : rType.length();
                                    int offset = typeHere.getOffset();
                                    ((JsObjectImpl) jsObject).addOccurrence(new OffsetRange(offset, jsObject.isAnonymous() ? offset : offset + typeLength));
                                }
                                moveOccurrenceOfProperties((JsObjectImpl) jsObject, this);
                                JsObject parent = jsObject.getParent();
                                if (parent != null && "window".equals(parent.getName())) {
                                    for (JsObject property : getProperties().values()) {
                                        if (property.isDeclared()) {
                                            JsObject gwProp = jsObject.getProperty(property.getName());
                                            if (gwProp == null) {
                                                jsObject.addProperty(property.getName(), property);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else if (type.getType().equals("@this;") && resolvedHere.size() == 1) {
                    // we expect something like self = this, so all properties of the object should be assigned to the this.
                    TypeUsage originalType = resolvedHere.iterator().next();
                    JsObject originalObject = ModelUtils.findJsObjectByName(global, originalType.getType());
                    if (originalObject != null) {
                        // move all properties to the original type.
                        // create copy of the new object, but without the properties
                        // the new object is needed for setting new assignment.
                        JsObject newObject = new JsObjectImpl(this.parent, this.declarationName,
                                this.getOffsetRange(), this.isDeclared(), this.getModifiers(), this.getMimeType(), this.getSourceLabel());
                        // replace the object with object without the properties 
                        parent.addProperty(this.getName(), newObject);
                        // copy all the properties to the original object that represents this
                        List <JsObject> propertiesCopy = new ArrayList<JsObject>(this.properties.values());
                        for (JsObject property : propertiesCopy) {
                            ModelUtils.moveProperty(originalObject, property);
                        }
                        for (Occurrence occurrence : this.occurrences) {
                            newObject.addOccurrence(occurrence.getOffsetRange());
                        }
                        newObject.addAssignment(new TypeUsage(originalObject.getFullyQualifiedName(), originalObject.getOffset(), true), assignments.keySet().iterator().next().intValue());
                    }
                }
                resolved.addAll(resolvedHere);
            }

            unresolved.clear();
            unresolved.addAll(resolved);
        }

        if (!isAnonymous()) {
            List<OffsetRange> docOccurrences = jsDocHolder.getOccurencesMap().get(getFullyQualifiedName());
            if (docOccurrences != null) {
                for (OffsetRange offsetRange : docOccurrences) {
                    addOccurrence(offsetRange);
                }
            }
        }
        
        if (!isAnonymous() && assignments.isEmpty()) {
            // try to recount occurrences
            JsObject global = ModelUtils.getGlobalObject(parent);
            List<Occurrence> correctedOccurrences = new ArrayList<Occurrence>();

            JsObjectImpl obAssignment = findRightTypeAssignment(getDeclarationName().getOffsetRange().getStart(), global);
            if (obAssignment != null && !obAssignment.getModifiers().contains(Modifier.PRIVATE)) {
                obAssignment.addOccurrence(getDeclarationName().getOffsetRange());
            }

            for (Occurrence occurrence : new ArrayList<Occurrence>(occurrences)) {
                obAssignment = findRightTypeAssignment(occurrence.getOffsetRange().getStart(), global);
                if (obAssignment != null && !obAssignment.getModifiers().contains(Modifier.PRIVATE)) {
                    obAssignment.addOccurrence(occurrence.getOffsetRange());
                } else {
                    correctedOccurrences.add(occurrence);
                }
            }

            for(Occurrence occurrence : correctedOccurrences){
                addOccurrence(occurrence.getOffsetRange());
            }
        }

        // resolving prototype types
        JsObject prototype = getProperty(ModelUtils.PROTOTYPE);
        if (prototype != null) {
            Collection<? extends TypeUsage> protoAssignments = prototype.getAssignments();
            if (protoAssignments != null && !protoAssignments.isEmpty()) {
                protoAssignments = new ArrayList<>(protoAssignments);
                Collection<? extends JsObject> variables = ModelUtils.getVariables(ModelUtils.getDeclarationScope(this));
                for (TypeUsage typeUsage : protoAssignments) {
                    for (JsObject variable : variables) {
                        if (typeUsage.getType().equals(variable.getName())) {
                            if (!typeUsage.getType().equals(variable.getFullyQualifiedName())) {
                                prototype.addAssignment(new TypeUsage(variable.getFullyQualifiedName(), typeUsage.getOffset(), true), typeUsage.getOffset());
                            }
                        }
                    }
                }
            }
        }

        // Try to find, whether this object is not also property of parent prototype.
        if (!isDeclared() && getParent() != null) {
            prototype = getParent().getProperty(ModelUtils.PROTOTYPE);
            if (prototype != null) {
                JsObject prototypeProperty = prototype.getProperty(getName());
                if (prototypeProperty != null && prototypeProperty.isDeclared()) {
                    // if there is also a property of parent prototype with the same name
                    // and is declared, move all the occurrences to the declared property
                    // and this property remove from parent.
                    for (Occurrence occurrence : getOccurrences()) {
                        prototypeProperty.addOccurrence(occurrence.getOffsetRange());
                    }
                    getParent().getProperties().remove(getName());
                }
            }
        }
    }

    protected void clearOccurrences() {
        occurrences.clear();
    }

    public static void moveOccurrenceOfProperties(JsObjectImpl original, JsObject created) {
        if (original.equals(created)) {
            return;
        }
        Collection<JsObject> prototypeChains = findPrototypeChain(original);
        for (JsObject jsObject : prototypeChains) {
            for (JsObject origProperty : jsObject.getProperties().values()) {
                if (origProperty.getModifiers().contains(Modifier.PUBLIC)
                        || origProperty.getModifiers().contains(Modifier.PROTECTED)) {
                    JsObjectImpl usedProperty = (JsObjectImpl) created.getProperty(origProperty.getName());
                    if (usedProperty != null) {
                        moveOccurrence((JsObjectImpl) origProperty, usedProperty);
                        moveOccurrenceOfProperties((JsObjectImpl) origProperty, usedProperty);
                    }
                }
            }
            JsObject prototype = jsObject.getProperty(ModelUtils.PROTOTYPE);
            if (prototype != null) {
                moveOccurrenceOfProperties((JsObjectImpl) prototype, created);
            }
        }
        
        if (!original.getAssignments().isEmpty() && created.getAssignments().isEmpty()) {
            // we are add type to help resolve other properties. 
            for(TypeUsage type : original.getAssignments()) {
                created.addAssignment(type, -1);
            }
        }

    }

    public static void moveOccurrence(JsObjectImpl original, JsObject created) {
        original.addOccurrence(created.getDeclarationName() != null ? created.getDeclarationName().getOffsetRange(): OffsetRange.NONE);
        for (Occurrence occur : created.getOccurrences()) {
            original.addOccurrence(occur.getOffsetRange());
        }
        ((JsObjectImpl) created).clearOccurrences();
        if (original.isDeclared() && created.isDeclared()) {
            ((JsObjectImpl) created).setDeclared(false); // the property is not declared here
        }
    }

    /**
     * Create prototype chain only from objects in the file
     *
     * @param object
     * @return
     */
    public static Collection<JsObject> findPrototypeChain(JsObject object) {
        List<JsObject> chain = new ArrayList<JsObject>();
        chain.add(object);
        chain.addAll(findPrototypeChain(object, new HashSet<String>()));
        return chain;
    }

    private static List<JsObject> findPrototypeChain(JsObject object, Set<String> alreadyCheck) {
        List<JsObject> result = new ArrayList<JsObject>();
        String fqn = object.getFullyQualifiedName();
        if (!alreadyCheck.contains(fqn)) {
            alreadyCheck.add(fqn);
            JsObject prototype = object.getProperty(ModelUtils.PROTOTYPE);
            if (prototype != null && !prototype.getAssignments().isEmpty()) {
                JsObject global = ModelUtils.getGlobalObject(object);
                for (TypeUsage type : prototype.getAssignments()) {
                    if (!type.isResolved()) {
                        Collection<TypeUsage> resolved = ModelUtils.resolveTypeFromSemiType(object, type);
                        for (TypeUsage rType : resolved) {
                            if (rType.isResolved()) {
                                JsObject fObject = ModelUtils.findJsObjectByName(global, rType.getType());
                                if (fObject != null) {
                                    result.add(fObject);
                                    result.addAll(findPrototypeChain(fObject, alreadyCheck));
                                }
                            }
                        }
                    } else {
                        JsObject fObject = ModelUtils.findJsObjectByName(global, type.getType());
                        if (fObject != null) {
                            result.add(fObject);
                            result.addAll(findPrototypeChain(fObject, alreadyCheck));
                        }
                    }
                }
            }
        }
        return result;
    }

    /**
     * This methods returns JsObject that represents a type for an assignment.
     *
     * @param offset
     * @return return the object
     */
    private JsObjectImpl findRightTypeAssignment(int offset, JsObject global) {
        Collection<? extends TypeUsage> findedAssignments;
        JsObject current;
        JsObject currentParent = this;
        // save the properties in a list to reuse it later
        List<String> propertyPath = new ArrayList<String>();
        do {
            current = currentParent;
            findedAssignments = current.getAssignmentForOffset(offset);
            propertyPath.add(current.getName());
            currentParent = current.getParent();
        } while (findedAssignments.isEmpty() && currentParent != null);

        for (TypeUsage type : findedAssignments) {
            // find the appropriate object for the type in the model
            current = ModelUtils.findJsObjectByName(global, type.getType());

            // map back the properties from the propertyPath to get the right object
            for (int i = propertyPath.size() - 2; i > -1 && current != null; i--) {
                current = current.getProperty(propertyPath.get(i));
            }
            if (current != null) {
                return (JsObjectImpl) current;
            }
        }

        return null;
    }

    @Override
    public Documentation getDocumentation() {
        return documentation;
    }

    @Override
    public void setDocumentation(Documentation doc) {
        this.documentation = doc;
    }

    @Override
    public boolean isDeprecated() {
        return getModifiers().contains(Modifier.DEPRECATED);
    }

    public void setDeprecated(boolean depreceted) {
        if (depreceted) {
            getModifiers().add(Modifier.DEPRECATED);
        } else {
            getModifiers().remove(Modifier.DEPRECATED);
        }
    }
    
    

//    @Override
//    public String toString() {
//        return "JsObjectImpl{" + "declarationName=" + declarationName + ", parent=" + parent + ", kind=" + kind + '}';
//    }

    @Override
    public boolean moveProperty(String name, JsObject newParent) {
        JsObject property = getProperty(name);
        if (property == null) {
            return false;
        }
        if (property instanceof JsObjectImpl) {
            String oldFQN = property.getFullyQualifiedName();
            ((JsObjectImpl)property).setParent(newParent);
            newParent.addProperty(name, property);
            String newFQN = property.getFullyQualifiedName();
            JsObject global = ModelUtils.getGlobalObject(this);
            if (global instanceof JsObjectImpl) {
                ((JsObjectImpl)global).correctAssignmentsInModel(oldFQN, newFQN, new HashSet<String>());
            }
            return properties.remove(name) != null;
        }
        return false;
    }
    
    private void correctAssignmentsInModel (String fromType, String toType, Set<String> done) {
        if (!done.contains(getFullyQualifiedName())) {
            done.add(getFullyQualifiedName());
            correctTypes(fromType, toType);
            for (JsObject property: getProperties().values()) {
                if (property instanceof JsObjectImpl) {
                    ((JsObjectImpl)property).correctAssignmentsInModel(fromType, toType, done);
                }
            }
        }
    }
    
    protected void correctTypes(String fromType, String toType) {
        for (Integer offset: assignments.keySet()) {
            Collection<TypeUsage> types = assignments.get(offset);
            List<TypeUsage> copy = new ArrayList<>(types);
            String typeR = null;
            for (TypeUsage type : copy) {
                typeR = replaceTypeInFQN(type.getType(), fromType, toType);
                if (typeR != null) {
                    types.remove(type);
                    types.add(new TypeUsage(typeR, type.getOffset(), type.isResolved()));
                }
            }
        }
    }
    
    /**
     * 
     * @param typeFQN type that where should be changed
     * @param fromType  the old type or part of a type
     * @param toType    the new type or part of a type
     * @return null, if it's not possible to replace or the result FQN
     */
    protected String replaceTypeInFQN(String typeFQN, String fromType, String toType) {
        String typeR = null;
        if (typeFQN.isEmpty()) {
            return null;
        }
        if (typeFQN.equals(fromType)) {
            typeR = toType;
        } else {
            int index = typeFQN.indexOf(fromType);
            if (typeFQN.startsWith(SemiTypeResolverVisitor.ST_START_DELIMITER)) {
                // it's semitype. we need to mask the semitypes
                int delEndIndex = typeFQN.indexOf(';');
                if (delEndIndex > 0 && index < delEndIndex) {
                    index = typeFQN.indexOf(fromType, delEndIndex);
                } 
                 
            }
            if (index > -1 && !typeFQN.contains(toType)
                    && (index == 0 || typeFQN.charAt(index - 1) == '.' || typeFQN.charAt(index - 1) == ';')
                    && ((index + fromType.length()) == typeFQN.length() || typeFQN.charAt(index + fromType.length()) == '.')) {
                boolean replace = (index == 0 || typeFQN.startsWith(SemiTypeResolverVisitor.ST_START_DELIMITER));
                if (!replace && index > 0) {
                    String typePrefix = typeFQN.substring(0, index - 1);
                    JsObject global = ModelUtils.getGlobalObject(this);
                    replace = ModelUtils.findJsObjectByName(global, typePrefix) != null;
                }
                if (replace) {
                    typeR = typeFQN.substring(0, index) + toType + typeFQN.substring(index + fromType.length());
                }
            }
        }
        return typeR;
    }
}
