/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.tests.viewers;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IBasicPropertyConstants;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;

public class TestModelContentProvider implements ITestModelListener,
		ITreeContentProvider {
    Viewer fViewer;

    @Override
	public void dispose() {
    }

    protected void doInsert(TestModelChange change) {
        if (fViewer instanceof ListViewer) {
            if (change.getParent() != null
                    && change.getParent().equals(fViewer.getInput())) {
                ((ListViewer) fViewer).add(change.getChildren());
            }
        } else if (fViewer instanceof TableViewer) {
            if (change.getParent() != null
                    && change.getParent().equals(fViewer.getInput())) {
                ((TableViewer) fViewer).add(change.getChildren());
            }
        } else if (fViewer instanceof AbstractTreeViewer) {
            ((AbstractTreeViewer) fViewer).add(change.getParent(), change
                    .getChildren());
        } else if (fViewer instanceof ComboViewer) {
            ((ComboViewer) fViewer).add(change.getChildren());
        } else {
            Assert.isTrue(false, "Unknown kind of viewer");
        }
    }

    protected void doNonStructureChange(TestModelChange change) {
        if (fViewer instanceof StructuredViewer) {
            ((StructuredViewer) fViewer).update(change.getParent(),
                    new String[] { IBasicPropertyConstants.P_TEXT });
        } else {
            Assert.isTrue(false, "Unknown kind of viewer");
        }
    }

    protected void doRemove(TestModelChange change) {
        if (fViewer instanceof ListViewer) {
            ((ListViewer) fViewer).remove(change.getChildren());
        } else if (fViewer instanceof TableViewer) {
            ((TableViewer) fViewer).remove(change.getChildren());
        } else if (fViewer instanceof AbstractTreeViewer) {
            ((AbstractTreeViewer) fViewer).remove(change.getChildren());
        } else if (fViewer instanceof ComboViewer) {
            ((ComboViewer) fViewer).remove(change.getChildren());
        } else {
            Assert.isTrue(false, "Unknown kind of viewer");
        }
    }

    protected void doStructureChange(TestModelChange change) {
        if (fViewer instanceof StructuredViewer) {
            ((StructuredViewer) fViewer).refresh(change.getParent());
        } else {
            Assert.isTrue(false, "Unknown kind of viewer");
        }
    }

    @Override
	public Object[] getChildren(Object element) {
        TestElement testElement = (TestElement) element;
        int count = testElement.getChildCount();
        TestElement[] children = new TestElement[count];
        for (int i = 0; i < count; ++i) {
			children[i] = testElement.getChildAt(i);
		}
        return children;
    }

    @Override
	public Object[] getElements(Object element) {
        return getChildren(element);
    }

    @Override
	public Object getParent(Object element) {
        return ((TestElement) element).getContainer();
    }

    @Override
	public boolean hasChildren(Object element) {
        return ((TestElement) element).getChildCount() > 0;
    }

    @Override
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        fViewer = viewer;
        TestElement oldElement = (TestElement) oldInput;
        if (oldElement != null) {
            oldElement.getModel().removeListener(this);
        }
        TestElement newElement = (TestElement) newInput;
        if (newElement != null) {
            newElement.getModel().addListener(this);
        }
    }

    public boolean isDeleted(Object element) {
        return ((TestElement) element).isDeleted();
    }

    @Override
	public void testModelChanged(TestModelChange change) {
        switch (change.getKind()) {
        case TestModelChange.INSERT:
            doInsert(change);
            break;
        case TestModelChange.REMOVE:
            doRemove(change);
            break;
        case TestModelChange.STRUCTURE_CHANGE:
            doStructureChange(change);
            break;
        case TestModelChange.NON_STRUCTURE_CHANGE:
            doNonStructureChange(change);
            break;
        default:
            throw new IllegalArgumentException("Unknown kind of change");
        }

        StructuredSelection selection = new StructuredSelection(change
                .getChildren());
        if ((change.getModifiers() & TestModelChange.SELECT) != 0) {
            ((StructuredViewer) fViewer).setSelection(selection);
        }
        if ((change.getModifiers() & TestModelChange.REVEAL) != 0) {
            Object element = selection.getFirstElement();
            if (element != null) {
                ((StructuredViewer) fViewer).reveal(element);
            }
        }
    }
}
