/*******************************************************************************
 * Copyright (c) 2009 Wind River Systems and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Wind River Systems - initial API and implementation
 *******************************************************************************/
package org.eclipe.debug.tests.viewer.model;

import java.util.Arrays;

import junit.framework.Assert;

import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelCheckProviderTarget;
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ICheckUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory2;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.Viewer;

/**
 * Test model for the use in unit tests.  This test model contains a set of 
 * elements in a tree structure.  It contains utility methods for modifying the 
 * model and for verifying that the viewer content matches the model.
 * 
 * @since 3.6
 */
public class TestModel implements IElementContentProvider, IElementLabelProvider, IModelProxyFactory2 , IElementMementoProvider {
    
    public static class TestElement extends PlatformObject {
        private final TestModel fModel;
        private final String fID;
        TestElement[] fChildren;
        String fLabelAppendix = "";
        boolean fExpanded;
        boolean fChecked;
        boolean fGrayed;
        
        public TestElement(TestModel model, String text, TestElement[] children) {
            this (model, text, false, false, children);
        }

        public TestElement(TestModel model, String text, boolean checked, boolean grayed, TestElement[] children) {
            fModel = model;
            fID = text;
            fChildren = children;
            fChecked = checked;
            fGrayed = grayed;
        }
        
        public TestModel getModel() {
            return fModel;
        }
        
        public Object getAdapter(Class adapter) {
            if (adapter.isInstance(fModel)) {
                return fModel;
            }
            return null;
        }
        
        public String getID() {
            return fID;
        }
        
        public void setLabelAppendix(String appendix) {
            fLabelAppendix = appendix;
        }
        
        public String getLabel() {
            return fID + fLabelAppendix;
        }
        
        public TestElement[] getChildren() {
            return fChildren;
        }
        
        public boolean isExpanded() {
            return fExpanded;
        }
        
        public boolean getGrayed() {
            return fGrayed;
        }
        
        public boolean getChecked() {
            return fChecked;
        }

        public void setChecked(boolean checked, boolean grayed) {
            fChecked = checked;
            fGrayed = grayed;
        }
        
        public boolean equals(Object obj) {
            return obj instanceof TestElement && fID.equals(((TestElement)obj).fID);
        }
        
        public int hashCode() {
            return fID.hashCode();
        }
        
        public String toString() {
            return getLabel();
        }
        
        public int indexOf(TestElement child) {
            return Arrays.asList(fChildren).indexOf(child);
        }
    }

    private class ModelProxy extends AbstractModelProxy {
        public void installed(Viewer viewer) {
            super.installed(viewer);
            ModelDelta rootDelta = TestModel.this.getBaseDelta(new ModelDelta(fInput, IModelDelta.NO_CHANGE));
            installSubModelProxies(fRootPath, rootDelta);
            fireModelChanged(rootDelta);
        }
        
        private void installSubModelProxies(TreePath path, ModelDelta delta) {
            TestElement element = getElement(path);
            if (element.fModel != TestModel.this) {
                // Found an element from a different model.  Install its proxy and return.
                delta.setFlags(delta.getFlags() | IModelDelta.INSTALL);
            } else {
                TestElement[] children = element.getChildren();
    
                for (int i = 0; i < children.length; i++) {
                    installSubModelProxies(path.createChildPath(children[i]), delta.addNode(children[i], IModelDelta.NO_CHANGE));
                }
            }
        }
    }

    private TestElement fRoot;
    private Object fInput = null;
    private TreePath fRootPath = TreePath.EMPTY;
    private ModelProxy fModelProxy;
    
    /**
     * Constructor private.  Use static factory methods instead. 
     */
    public TestModel() {}
    
    public TestElement getRootElement() {
        return fRoot;
    }
    
    ModelDelta getBaseDelta(ModelDelta rootDelta) {
        ModelDelta delta = rootDelta;
        for (int i = 0; i < fRootPath.getSegmentCount(); i++) {
        	ModelDelta subDelta = delta.getChildDelta(fRootPath.getSegment(i));
        	if (subDelta == null) {
        		subDelta = delta.addNode(fRootPath.getSegment(i), IModelDelta.NO_CHANGE);
        	}
        	delta = subDelta;
        }
        return delta;
    }

    public int getModelDepth() {
        return getDepth(getRootElement(), 0);
    }
    
    private int getDepth(TestElement element, int atDepth) {
        TestElement[] children = element.getChildren(); 
        if (children.length == 0) {
            return atDepth;
        }
        int depth = atDepth + 1;
        for (int i = 0; i < children.length; i++) {
            depth = Math.max(depth, getDepth(children[i], atDepth + 1));
        }

        return depth;
    }
    
    public void update(IHasChildrenUpdate[] updates) {
        for (int i = 0; i < updates.length; i++) {
            TestElement element = (TestElement)updates[i].getElement();
            updates[i].setHasChilren(element.getChildren().length > 0);
            updates[i].done();
        }
    }
    
    public void update(IChildrenCountUpdate[] updates) {
        for (int i = 0; i < updates.length; i++) {
            TestElement element = (TestElement)updates[i].getElement();
            updates[i].setChildCount(element.getChildren().length);
            updates[i].done();
        }
    }
    
    public void update(IChildrenUpdate[] updates) {
        for (int i = 0; i < updates.length; i++) {
            TestElement element = (TestElement)updates[i].getElement();
            int endOffset = updates[i].getOffset() + updates[i].getLength();
            for (int j = updates[i].getOffset(); j < endOffset; j++) {
                if (j < element.getChildren().length) {
                    updates[i].setChild(element.getChildren()[j], j);
                }
            }
            updates[i].done();
        }
    }
    
    public void update(ILabelUpdate[] updates) {
        for (int i = 0; i < updates.length; i++) {
            TestElement element = (TestElement)updates[i].getElement();
            updates[i].setLabel(element.fID, 0);
            if (updates[i] instanceof ICheckUpdate && 
                Boolean.TRUE.equals(updates[i].getPresentationContext().getProperty(ICheckUpdate.PROP_CHECK))) 
            {
                ((ICheckUpdate)updates[i]).setChecked(element.getChecked(), element.getGrayed());
            }
            updates[i].done();
        }        
    }
    
    public final static String ELEMENT_MEMENTO_ID = "id";
    
    public void compareElements(IElementCompareRequest[] updates) {
        for (int i = 0; i < updates.length; i++) {
            String elementID = ((TestElement)updates[i].getElement()).getID();
            String mementoID = updates[i].getMemento().getString(ELEMENT_MEMENTO_ID);
            updates[i].setEqual( elementID.equals(mementoID) );
            updates[i].done();
        }        
        
    }
    
    public void encodeElements(IElementMementoRequest[] updates) {
        for (int i = 0; i < updates.length; i++) {
            String elementID = ((TestElement)updates[i].getElement()).getID();
            updates[i].getMemento().putString(ELEMENT_MEMENTO_ID, elementID);
            updates[i].done();
        }        
    }
    
    
    public void elementChecked(IPresentationContext context, Object viewerInput, TreePath path, boolean checked) {
        TestElement element = getElement(path); 
        Assert.assertFalse(element.getGrayed());
        element.setChecked(checked, false);
    }
    
    public IModelProxy createTreeModelProxy(Object input, TreePath path, IPresentationContext context) {
        fModelProxy = new ModelProxy();
        fInput = input;
        fRootPath = path;
        return fModelProxy;
    }
    
    public IModelProxy getModelProxy() {
        return fModelProxy;
    }
    
    public TestElement getElement(TreePath path) {
        if (path.getSegmentCount() == 0) {
            return getRootElement();
        } else {
            return (TestElement)path.getLastSegment();
        }
    }

    public void setAllExpanded() {
        doSetExpanded(fRoot);
    }
    
    private void doSetExpanded(TestElement element) {
        element.fExpanded = true;
        for (int i = 0; i < element.fChildren.length; i++) {
            doSetExpanded(element.fChildren[i]);
        }
    }

    public void setAllAppendix(String appendix) {
        doSetAllAppendix(fRoot, appendix);
    }
    
    private void doSetAllAppendix(TestElement element, String appendix) {
        element.setLabelAppendix(appendix);
        for (int i = 0; i < element.fChildren.length; i++) {
            doSetAllAppendix(element.fChildren[i], appendix);
        }
    }

    public void validateData(ITreeModelViewer viewer, TreePath path) {
        
        validateData(viewer, path, false);
    }

    public void validateData(ITreeModelViewer _viewer, TreePath path, boolean expandedElementsOnly) {
        ITreeModelContentProviderTarget viewer = (ITreeModelContentProviderTarget)_viewer;
        TestElement element = getElement(path);
        if ( Boolean.TRUE.equals(_viewer.getPresentationContext().getProperty(ICheckUpdate.PROP_CHECK)) ) {
            ITreeModelCheckProviderTarget checkTarget = (ITreeModelCheckProviderTarget)_viewer;  
            Assert.assertEquals(element.getChecked(), checkTarget.getElementChecked(path));
            Assert.assertEquals(element.getGrayed(), checkTarget.getElementGrayed(path));
        }
        
        if (!expandedElementsOnly || path.getSegmentCount() == 0 || viewer.getExpandedState(path) ) {
            TestElement[] children = element.getChildren();
            Assert.assertEquals(children.length, viewer.getChildCount(path));

            for (int i = 0; i < children.length; i++) {
                Assert.assertEquals(children[i], viewer.getChildElement(path, i));
                validateData(viewer, path.createChildPath(children[i]), expandedElementsOnly);
            }
        } else if (!viewer.getExpandedState(path)) {
            // If element not expanded, verify the plus sign.
            Assert.assertEquals(viewer.getHasChildren(path), element.getChildren().length > 0);
        }
    }

    public void setRoot(TestElement root) {
        fRoot = root;
    }
    
    public void postDelta(IModelDelta delta) {
        fModelProxy.fireModelChanged(delta);
    }
    
    /** Create or retrieve delta for given path
     * @param combine if then new deltas for the given path are created. If false existing ones are reused.
     */
    private ModelDelta getElementDelta(ModelDelta baseDelta, TreePath path, boolean combine) {
        TestElement element = getRootElement();
        ModelDelta delta = baseDelta;
        
        for (int i = 0; i < path.getSegmentCount(); i++) {
            TestElement[] children = element.getChildren(); 
            delta.setChildCount(children.length);
            Object segment = path.getSegment(i);
            int j;
            for (j = 0; j < children.length; j++) {
                if (segment.equals(children[j])) {
                    element = children[j];
                    ModelDelta nextDelta = null;
                    if (combine) {
                    	nextDelta = delta.getChildDelta(element);
                    }
                    if (nextDelta == null) {
                    	nextDelta = delta.addNode(element, j, IModelDelta.NO_CHANGE);
                    }
                    delta = nextDelta;
                    break;
                }
            }
            if (j == children.length) {
                throw new IllegalArgumentException("Invalid path");
            }
        }
        return delta;
        
    }
    
    private TreePath getRelativePath(TreePath path) {
        Object[] segments = new Object[path.getSegmentCount() - fRootPath.getSegmentCount()];
        for (int i = fRootPath.getSegmentCount(), _i = 0; i < path.getSegmentCount(); i++, _i++) {
            segments[_i] = path.getSegment(i);
        }
        return new TreePath(segments);
    }
    
    public ModelDelta appendElementLabel(TreePath path, String labelAppendix) {
        Assert.assertTrue(path.startsWith(fRootPath, null));
        ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
        ModelDelta baseDelta = getBaseDelta(rootDelta);
        TreePath relativePath = getRelativePath(path);
        TestElement element = getElement(relativePath);
        ModelDelta delta = getElementDelta(baseDelta, relativePath, false);
        element.setLabelAppendix(labelAppendix);
        delta.setFlags(delta.getFlags() | IModelDelta.STATE);

        return rootDelta;
    }

    public ModelDelta setElementChecked(TreePath path, boolean checked, boolean grayed) {
        Assert.assertTrue(path.startsWith(fRootPath, null));
        ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
        ModelDelta baseDelta = getBaseDelta(rootDelta);
        TreePath relativePath = getRelativePath(path);
        TestElement element = getElement(relativePath);
        ModelDelta delta = getElementDelta(baseDelta, relativePath, false);
        element.setChecked(checked, grayed);
        delta.setFlags(delta.getFlags() | IModelDelta.STATE);

        return rootDelta;
    }

    public ModelDelta setElementChildren(TreePath path, TestElement[] children) {
        Assert.assertTrue(path.startsWith(fRootPath, null));
        ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
        ModelDelta baseDelta = getBaseDelta(rootDelta);
        TreePath relativePath = getRelativePath(path);

        // Find the parent element and generate the delta node for it.
        TestElement element = getElement(relativePath);
        ModelDelta delta = getElementDelta(baseDelta, relativePath, false);
        
        // Set the new children array
        element.fChildren = children;
        
        // Add the delta flag and update the child count in the parent delta.        
        delta.setFlags(delta.getFlags() | IModelDelta.CONTENT);
        delta.setChildCount(children.length);
        
        return rootDelta;
    }
    
    public ModelDelta replaceElementChild(TreePath parentPath, int index, TestElement child) {
        ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
        ModelDelta baseDelta = getBaseDelta(rootDelta);
        TreePath relativePath = getRelativePath(parentPath);
        
        TestElement element = getElement(relativePath);
        ModelDelta delta= getElementDelta(baseDelta, relativePath, false);
        TestElement oldChild = element.fChildren[index]; 
        element.fChildren[index] = child;
        delta.addNode(oldChild, child, IModelDelta.REPLACED);
        // TODO: set replacement index!?!
        
        return rootDelta;
    }    

    public ModelDelta addElementChild(TreePath parentPath, int index, TestElement newChild) {
        ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
        ModelDelta baseDelta = getBaseDelta(rootDelta);
        TreePath relativePath = getRelativePath(parentPath);

        // Find the parent element and generate the delta node for it.
        TestElement element = getElement(relativePath);
        ModelDelta delta= getElementDelta(baseDelta, relativePath, false);

        // Add the new element
        element.fChildren = doInsertElementInArray(element.fChildren, index, newChild);
        
        // Add the delta flag and update the child count in the parent delta.
        delta.setChildCount(element.getChildren().length);
        delta.addNode(newChild, IModelDelta.ADDED);
        
        return rootDelta;
    }    

    public ModelDelta insertElementChild(TreePath parentPath, int index, TestElement newChild) {
        return insertElementChild(null, parentPath, index, newChild);
    }    

    public ModelDelta insertElementChild(ModelDelta rootDelta, TreePath parentPath, int index, TestElement newChild) {
        if (rootDelta == null) {
        	rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
        }
        ModelDelta baseDelta = getBaseDelta(rootDelta);
        TreePath relativePath = getRelativePath(parentPath);

        // Find the parent element and generate the delta node for it.
        TestElement element = getElement(relativePath);
        ModelDelta delta= getElementDelta(baseDelta, relativePath, false);
        
        // Add the new element
        element.fChildren = doInsertElementInArray(element.fChildren, index, newChild);
        
        // Add the delta flag and update the child count in the parent delta.
        delta.setChildCount(element.getChildren().length);
        delta.addNode(newChild, index, IModelDelta.INSERTED);
        
        return rootDelta;
    }    
    
    private TestElement[] doInsertElementInArray(TestElement[] children, int index, TestElement newChild) {
        // Create the new children array add the element to it and set it to 
        // the parent.
        TestElement[] newChildren = new TestElement[children.length + 1];
        System.arraycopy(children, 0, newChildren, 0, index);
        newChildren[index] = newChild;
        System.arraycopy(children, index, newChildren, index + 1, children.length - index);
        return newChildren;
    }
    
    public ModelDelta removeElementChild(TreePath parentPath, int index) {
        ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
        ModelDelta baseDelta = getBaseDelta(rootDelta);

        // Find the parent element and generate the delta node for it.
        TestElement element = getElement(parentPath);
        ModelDelta delta= getElementDelta(baseDelta, parentPath, false);
        
        // Create a new child array with the element removed
        TestElement[] children = element.getChildren();
        TestElement childToRemove = children[index];
        TestElement[] newChildren = new TestElement[children.length - 1];
        System.arraycopy(children, 0, newChildren, 0, index);
        System.arraycopy(children, index + 1, newChildren, index, children.length - index - 1);
        element.fChildren = newChildren;

        // Add the delta flag and update the child count in the parent delta.
        delta.setChildCount(element.getChildren().length);
        delta.addNode(childToRemove, index, IModelDelta.REMOVED);
        
        return rootDelta;
    }        

    public TreePath findElement(String label) {
        return findElement(TreePath.EMPTY, label);
    }

    public TreePath findElement(TreePath startPath, String label) {
        TestElement element = getElement(startPath);
        for (int i = 0; i < element.getChildren().length; i++) {
            TestElement child = element.getChildren()[i];
            TreePath path = startPath.createChildPath(child);
            if ( label.equals(child.getLabel()) ) {
                return path;
            } else {
                TreePath subPath = findElement(path, label);
                if (subPath != null) {
                    return subPath;
                }
            }
        }
        return null;
    }
    
    public String toString() {
        return getElementString(fRoot, "");
    }
    
    public String getElementString(TestElement element, String indent) {
        StringBuffer builder = new StringBuffer();
        builder.append(indent); 
        builder.append(element.toString());
        builder.append('\n');
        TestElement[] children = element.getChildren();
        for (int i = 0; i < children.length; i++) {
            builder.append(getElementString(children[i], indent + "  "));
        }
        return builder.toString();
    }
    
    public static TestModel simpleSingleLevel() {
        TestModel model = new TestModel();
        model.setRoot( new TestElement(model, "root", new TestElement[] {
            new TestElement(model, "1", true, true, new TestElement[0]),
            new TestElement(model, "2", true, false, new TestElement[0]),
            new TestElement(model, "3", false, true, new TestElement[0]),
            new TestElement(model, "4", false, false, new TestElement[0]),
            new TestElement(model, "5", new TestElement[0]),
            new TestElement(model, "6", new TestElement[0])
        }) );
        return model;
    }
    
    public static TestModel simpleMultiLevel() {
        TestModel model = new TestModel();
        model.setRoot( new TestElement(model, "root", new TestElement[] {
            new TestElement(model, "1", new TestElement[0]),
            new TestElement(model, "2", true, false, new TestElement[] {
                new TestElement(model, "2.1", true, true, new TestElement[0]),
                new TestElement(model, "2.2", false, true, new TestElement[0]),
                new TestElement(model, "2.3", true, false, new TestElement[0]),
            }),
            new TestElement(model, "3", new TestElement[] {
                new TestElement(model, "3.1", new TestElement[] {
                    new TestElement(model, "3.1.1", new TestElement[0]),
                    new TestElement(model, "3.1.2", new TestElement[0]),
                    new TestElement(model, "3.1.3", new TestElement[0]),
                }),
                new TestElement(model, "3.2", new TestElement[] {
                    new TestElement(model, "3.2.1", new TestElement[0]),
                    new TestElement(model, "3.2.2", new TestElement[0]),
                    new TestElement(model, "3.2.3", new TestElement[0]),
                }),
                new TestElement(model, "3.3", new TestElement[] {
                    new TestElement(model, "3.3.1", new TestElement[0]),
                    new TestElement(model, "3.3.2", new TestElement[0]),
                    new TestElement(model, "3.3.3", new TestElement[0]),
                }),
            })
        }) );
        return model;
    }

    public static TestModel compositeMultiLevel() {
        TestModel m2 = new TestModel();
        m2.setRoot( new TestElement(m2, "m2.root", new TestElement[] {
            new TestElement(m2, "m2.1", new TestElement[0]),
            new TestElement(m2, "m2.2", true, false, new TestElement[] {
                new TestElement(m2, "m2.2.1", true, true, new TestElement[0]),
                new TestElement(m2, "m2.2.2", false, true, new TestElement[0]),
                new TestElement(m2, "m2.2.3", true, false, new TestElement[0]),
            }),
        }) );

        TestModel m3 = new TestModel();
        m3.setRoot( new TestElement(m3, "m3.root", new TestElement[] {
            new TestElement(m3, "m3.1", new TestElement[0]),
            new TestElement(m3, "m3.2", true, false, new TestElement[] {
                new TestElement(m3, "m3.2.1", true, true, new TestElement[0]),
                new TestElement(m3, "m3.2.2", false, true, new TestElement[0]),
                new TestElement(m3, "m3.2.3", true, false, new TestElement[0]),
            }),
        }) );

        TestModel m4 = new TestModel();
        m4.setRoot( new TestElement(m4, "m4.root", new TestElement[] {
            new TestElement(m4, "m4.1", new TestElement[0]),
            new TestElement(m4, "m4.2", true, false, new TestElement[] {
                new TestElement(m4, "m4.2.1", true, true, new TestElement[0]),
                new TestElement(m4, "m4.2.2", false, true, new TestElement[0]),
                new TestElement(m4, "m4.2.3", true, false, new TestElement[0]),
            }),
        }) );

        TestModel m1 = new TestModel();
        m1.setRoot( new TestElement(m1, "m1.root", new TestElement[] {
            new TestElement(m1, "m1.1", new TestElement[0]),
            new TestElement(m1, "m1.2", true, false, new TestElement[] {
                m2.fRoot,
                m3.fRoot,
                m4.fRoot,
            }),
        }) );


        return m1;
    }

    
}
