/*=============================================================================#
 # Copyright (c) 2010, 2020 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.r.ui.dataeditor;

import static org.eclipse.statet.internal.r.ui.RUIPlugin.logError;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import com.ibm.icu.util.TimeZone;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;

import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.Status;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.jcommons.status.eplatform.EStatusUtils;
import org.eclipse.statet.jcommons.ts.core.SystemRunnable;
import org.eclipse.statet.jcommons.ts.core.Tool;
import org.eclipse.statet.jcommons.ts.core.ToolRunnable;
import org.eclipse.statet.jcommons.ts.core.ToolService;

import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.ecommons.waltable.coordinate.PositionId;
import org.eclipse.statet.ecommons.waltable.data.ControlData;
import org.eclipse.statet.ecommons.waltable.data.IDataProvider;
import org.eclipse.statet.ecommons.waltable.sort.ISortModel;
import org.eclipse.statet.ecommons.waltable.sort.SortDirection;

import org.eclipse.statet.r.core.model.RElementName;
import org.eclipse.statet.r.core.tool.TmpUtils;
import org.eclipse.statet.r.nico.ICombinedRDataAdapter;
import org.eclipse.statet.r.ui.dataeditor.IRDataTableInput;
import org.eclipse.statet.r.ui.dataeditor.IRDataTableVariable;
import org.eclipse.statet.r.ui.dataeditor.RDataTableColumn;
import org.eclipse.statet.rj.data.RCharacterStore;
import org.eclipse.statet.rj.data.RDataUtils;
import org.eclipse.statet.rj.data.RFactorStore;
import org.eclipse.statet.rj.data.RIntegerStore;
import org.eclipse.statet.rj.data.RLanguage;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.data.RObjectFactory;
import org.eclipse.statet.rj.data.RStore;
import org.eclipse.statet.rj.data.RVector;
import org.eclipse.statet.rj.data.UnexpectedRDataException;
import org.eclipse.statet.rj.data.impl.DefaultRObjectFactory;
import org.eclipse.statet.rj.data.impl.RFactorStructStore;
import org.eclipse.statet.rj.services.BasicFQRObjectRef;
import org.eclipse.statet.rj.services.FQRObjectRef;
import org.eclipse.statet.rj.services.FunctionCall;
import org.eclipse.statet.rj.services.RService;
import org.eclipse.statet.rj.services.util.dataaccess.AbstractRDataAdapter;
import org.eclipse.statet.rj.services.util.dataaccess.LazyRStore;
import org.eclipse.statet.rj.services.util.dataaccess.LazyRStore.Fragment;
import org.eclipse.statet.rj.services.util.dataaccess.RDataAssignment;
import org.eclipse.statet.rj.ts.core.RToolService;


public abstract class AbstractRDataProvider<T extends RObject> implements IDataProvider {
	
	
	public static final ControlData LOADING= new ControlData(ControlData.ASYNC, "loading...");
	public static final ControlData ERROR= new ControlData(ControlData.ERROR, "ERROR");
	public static final ControlData NA= new ControlData(ControlData.NA, "NA"); //$NON-NLS-1$
	public static final ControlData DUMMY= new ControlData(0, ""); //$NON-NLS-1$
	
	protected static final RElementName BASE_NAME= RElementName.create(RElementName.MAIN_DEFAULT, "x"); //$NON-NLS-1$
	
	
	static final void checkCancel(final Exception e) throws StatusException {
		if (e instanceof StatusException
				&& ((StatusException) e).getStatus().getSeverity() == Status.CANCEL) {
			throw (StatusException) e;
		}
	}
	
	
	public static final class SortColumn {
		
		
		private final long id;
		
		public final boolean decreasing;
		
		
		public SortColumn(final long columnId, final boolean decreasing) {
			this.id= columnId;
			this.decreasing= decreasing;
		}
		
		
		public long getId() {
			return this.id;
		}
		
		public long getIdx() {
			return (this.id & PositionId.NUM_MASK);
		}
		
		
		@Override
		public int hashCode() {
			final int h= (int) (this.id ^ (this.id >>> 32));
			return (this.decreasing) ? (-h) : h;
		}
		
		@Override
		public boolean equals(final Object obj) {
			if (!(obj instanceof SortColumn)) {
				return false;
			}
			final SortColumn other= (SortColumn) obj;
			return (this.id == other.id && this.decreasing == other.decreasing);
		}
		
	}
	
	public static interface IDataProviderListener {
		
		
		static final int ERROR_STRUCT_CHANGED= 1;
		
		
		void onInputInitialized(boolean structChanged);
		
		void onInputFailed(int error);
		
		void onRowCountChanged();
		
		void onRowsChanged(long begin, long end);
		
	}
	
	private static final long DEFAULT_WAIT= 25_000000;
	private static final long CANCEL_WAIT= 200_000000;
	private static final long BLOCKING_WAIT= 300_000000;
	
	private class MainLock extends Lock implements LazyRStore.Updater {
		
		
		private final List<Fragment> waitingFragments= new ArrayList<>();
		
		
		@Override
		public void scheduleUpdate(final LazyRStore store,
				final RDataAssignment assignment, final Fragment fragment,
				final int flags, final ProgressMonitor m) {
			long waitNanos;
			if (!this.scheduled) {
				this.scheduled= true;
				AbstractRDataProvider.this.schedule(AbstractRDataProvider.this.updateRunnable);
				
				waitNanos= ((flags & FORCE_SYNC) != 0) ? 0 : DEFAULT_WAIT;
			}
			else {
				waitNanos= ((flags & FORCE_SYNC) != 0) ? 0 : -1;
			}
			
			if (waitNanos >= 0 && fragment != null) {
				this.waitingFragments.add(fragment);
				this.worker.signalAll();
//				long blockingMonitor= (monitor instanceof IProgressMonitorWithBlocking) ? 0 : -1;
				try {
					if (waitNanos == 0) {
						do {
							// wait required to check cancel state
							waitNanos= this.requestor.awaitNanos(CANCEL_WAIT);
							
//							if (blockingMonitor >= 0 && blockingMonitor < BLOCKING_WAIT) {
//								blockingMonitor+= CANCEL_WAIT - waitNanos;
//								if (blockingMonitor >= BLOCKING_WAIT) {
//									((IProgressMonitorWithBlocking) monitor).setBlocked(
//											new Status(IStatus.INFO, RUI.BUNDLE_ID, "Waiting for R."));
//								}
//							}
						}
						while (this.waitingFragments.contains(fragment)
								&& this.state == 0
								&& (m == null || !m.isCanceled()) );
					}
					else {
						do {
							waitNanos= this.requestor.awaitNanos(waitNanos);
						}
						while (this.waitingFragments.contains(fragment)
								&& this.state == 0
								&& (m == null || !m.isCanceled())
								&& (waitNanos > 0) );
					}
				}
				catch (final InterruptedException e) {}
				finally {
					this.waitingFragments.remove(fragment);
					
//					if (blockingMonitor >= BLOCKING_WAIT) {
//						((IProgressMonitorWithBlocking) monitor).clearBlocked();
//					}
				}
			}
		}
		
		void notify(final Object obj) {
			if (this.waitingFragments.remove(obj)) {
				this.requestor.signalAll();
			}
		}
		
		@Override
		void clear() {
			this.waitingFragments.clear();
			super.clear();
		}
		
	}
	
	protected class ColumnDataProvider implements IDataProvider {
		
		
		public ColumnDataProvider() {
		}
		
		
		@Override
		public long getColumnCount() {
			return AbstractRDataProvider.this.getColumnCount();
		}
		
		@Override
		public long getRowCount() {
			return 1;
		}
		
		@Override
		public Object getDataValue(final long columnIndex, final long rowIndex,
				final int flags, final IProgressMonitor monitor) {
			try {
				final LazyRStore.Fragment<T> fragment= AbstractRDataProvider.this.fragmentsLock.getFragment(
						AbstractRDataProvider.this.dataStore, 0, columnIndex,
						flags, EStatusUtils.convert(monitor) );
				if (fragment != null) {
					return getColumnName(fragment, columnIndex);
				}
				else {
					return handleMissingData(flags);
				}
			}
			catch (final LoadDataException e) {
				return handleLoadDataException(e, flags);
			}
		}
		
		@Override
		public void setDataValue(final long columnIndex, final long rowIndex, final Object newValue) {
			throw new UnsupportedOperationException();
		}
		
	}
	
	protected class RowDataProvider implements IDataProvider {
		
		
		private final LazyRStore<RVector<?>> rowNamesStore= new LazyRStore<>(AbstractRDataProvider.this.rowCount, 1,
				10, AbstractRDataProvider.this.fragmentsLock);
		
		
		public RowDataProvider() {
		}
		
		
		@Override
		public long getColumnCount() {
			return 1;
		}
		
		@Override
		public long getRowCount() {
			return AbstractRDataProvider.this.getRowCount();
		}
		
		@Override
		public Object getDataValue(final long columnIndex, final long rowIndex,
				final int flags, final IProgressMonitor monitor) {
			try {
				final LazyRStore.Fragment<RVector<?>> fragment= AbstractRDataProvider
						.this.fragmentsLock.getFragment(this.rowNamesStore, rowIndex, 0,
								flags, EStatusUtils.convert(monitor) );
				if (fragment != null) {
					final RVector<?> vector= fragment.getRObject();
					if (vector != null) {
						RStore<?> names= vector.getNames();
						if (names == null) {
							names= vector.getData();
						}
						return names.get(rowIndex - fragment.getRowBeginIdx());
					}
					return Long.toString(rowIndex + 1);
				}
				else {
					return handleMissingData(flags);
				}
			}
			catch (final LoadDataException e) {
				return handleLoadDataException(e, flags);
			}
		}
		
		public long getRowIdx(final long rowIndex) {
			try {
				final LazyRStore.Fragment<RVector<?>> fragment= AbstractRDataProvider
						.this.fragmentsLock.getFragment(this.rowNamesStore, rowIndex, 0, 0, null);
				if (fragment != null) {
					final RVector<?> vector= fragment.getRObject();
					if (vector != null) {
						final RStore<?> idxs= vector.getData();
						return ((idxs.getStoreType() == RStore.INTEGER) ?
										(long) idxs.getInt(rowIndex - fragment.getRowBeginIdx()) :
										(long) idxs.getNum(rowIndex - fragment.getRowBeginIdx()) )
								- 1;
					}
					return rowIndex;
				}
				else {
					return -1;
				}
			}
			catch (final LoadDataException e) {
				return -2;
			}
		}
		
		@Override
		public void setDataValue(final long columnIndex, final long rowIndex, final Object newValue) {
			throw new UnsupportedOperationException();
		}
		
	}
	
	protected class SortModel implements ISortModel {
		
		
		@Override
		public List<Long> getSortedColumnIds() {
			final SortColumn sortColumn= getSortColumn();
			if (sortColumn != null) {
				return Collections.singletonList(sortColumn.id);
			}
			return Collections.<Long>emptyList();
		}
		
		@Override
		public void sort(final long columnId, final SortDirection sortDirection, final boolean accumulate) {
			SortColumn sortColumn;
			switch (sortDirection) {
			case ASC:
				sortColumn= new SortColumn(columnId, false);
				break;
			case DESC:
				sortColumn= new SortColumn(columnId, true);
				break;
			default:
				sortColumn= null;
				break;
			}
			setSortColumn(sortColumn);
		}
		
		@Override
		public int getSortOrder(final long columnId) {
			final SortColumn sortColumn= getSortColumn();
			if (sortColumn != null && sortColumn.id == columnId) {
				return 0;
			}
			return -1;
		}
		
		@Override
		public boolean isSorted(final long columnId) {
			final SortColumn sortColumn= getSortColumn();
			if (sortColumn != null && sortColumn.id == columnId) {
				return true;
			}
			return false;
		}
		
		@Override
		public SortDirection getSortDirection(final long columnId) {
			final SortColumn sortColumn= getSortColumn();
			if (sortColumn != null && sortColumn.id == columnId) {
				return (!sortColumn.decreasing) ? SortDirection.ASC : SortDirection.DESC;
			}
			return SortDirection.NONE;
		}
		
		@Override
		public void clear() {
			setSortColumn(null);
		}
		
	}
	
	
	private final ToolRunnable initRunnable= new SystemRunnable() {
		
		@Override
		public String getTypeId() {
			return "r/dataeditor/init";
		}
		
		@Override
		public String getLabel() {
			return "Prepare Data Viewer (" + AbstractRDataProvider.this.input.getName() + ")";
		}
		
		@Override
		public boolean canRunIn(final Tool tool) {
			return true; // TODO
		}
		
		@Override
		public boolean changed(final int event, final Tool tool) {
			if (event == MOVING_FROM) {
				return false;
			}
			return true;
		}
		
		@Override
		public void run(final ToolService service, final ProgressMonitor m) throws StatusException {
			runInit((RToolService) service, m);
		}
		
	};
	
	private final ToolRunnable updateRunnable= new SystemRunnable() {
		
		@Override
		public String getTypeId() {
			return "r/dataeditor/load"; //$NON-NLS-1$
		}
		
		@Override
		public String getLabel() {
			return "Load Data (" + AbstractRDataProvider.this.input.getName() + ")";
		}
		
		@Override
		public boolean canRunIn(final Tool tool) {
			return true; // TODO
		}
		
		@Override
		public boolean changed(final int event, final Tool tool) {
			switch (event) {
			case MOVING_FROM:
				return false;
			case REMOVING_FROM:
			case BEING_ABANDONED:
				AbstractRDataProvider.this.fragmentsLock.lock();
				try {
					AbstractRDataProvider.this.fragmentsLock.scheduled= false;
					AbstractRDataProvider.this.fragmentsLock.clear();
				}
				finally {
					AbstractRDataProvider.this.fragmentsLock.unlock();
				}
				break;
			default:
				break;
			}
			return true;
		}
		
		@Override
		public void run(final ToolService service, final ProgressMonitor m) throws StatusException {
			runUpdate((RToolService) service, m);
		}
		
	};
	
	private final ToolRunnable cleanRunnable= new SystemRunnable() {
		
		@Override
		public String getTypeId() {
			return "r/dataeditor/clean"; //$NON-NLS-1$
		}
		
		@Override
		public String getLabel() {
			return "Clean Cache (" + AbstractRDataProvider.this.input.getName() + ")";
		}
		
		@Override
		public boolean canRunIn(final Tool tool) {
			return true; // TODO
		}
		
		@Override
		public boolean changed(final int event, final Tool tool) {
			switch (event) {
			case MOVING_FROM:
			case REMOVING_FROM:
				return false;
			default:
				break;
			}
			return true;
		}
		
		@Override
		public void run(final ToolService service, final ProgressMonitor m) throws StatusException {
			runClean((RToolService) service, m);
		}
		
	};
	
	
	private final Display realm;
	
	private final IRDataTableInput input;
	
	private final long columnCount;
	private long fullRowCount;
	private long rowCount;
	
	private final CopyOnWriteIdentityListSet<IDataProviderListener> dataListeners= new CopyOnWriteIdentityListSet<>();
	
	private boolean initScheduled;
	private volatile boolean disposeScheduled;
	
	
	private RDataTableContentDescription description;
	
	private final IDataProvider columnDataProvider;
	private final IDataProvider rowDataProvider;
	
	private final IDataProvider columnLabelProvider;
	private final IDataProvider rowLabelProvider;
	
	private final MainLock fragmentsLock= new MainLock();
	
	protected final AbstractRDataAdapter<T, T> adapter;
	private final LazyRStore<T> dataStore;
	
	private final List<Object> activeOperations= new ArrayList<>();
	
	private boolean updateSorting;
	private boolean updateFiltering;
	
	private final StringBuilder rStringBuilder= new StringBuilder(128);
	private TmpUtils.Item rTmpItem; // only in R jobs
	private T rObjectStruct;
	
	private final ISortModel sortModel;
	private SortColumn sortColumn= null;
	private String rCacheSort; // only in R jobs
	
	private String filter;
	private String rCacheFilter;
	
	private boolean updateIdx; // only in R jobs
	private String rCacheIdx; // only in R jobs
	private String rCacheIdxR; // only in R jobs
	
	private final FindManager findManager;
	
	
	protected AbstractRDataProvider(final IRDataTableInput input,
			final AbstractRDataAdapter<T, T> adapter, final T initialRObject) {
		this.realm= UIAccess.getDisplay();
		this.input= input;
		
		this.adapter= adapter;
		this.fullRowCount= this.rowCount= this.adapter.getRowCount(initialRObject);
		this.columnCount= this.adapter.getColumnCount(initialRObject);
		
		final int dataMax;
		if (this.columnCount <= 25) {
			dataMax= 10;
		}
		else if (this.columnCount <= 50) {
			dataMax= 20;
		}
		else {
			dataMax= 25;
		}
		this.dataStore= new LazyRStore<>(this.rowCount, this.columnCount, dataMax, this.fragmentsLock);
		this.findManager= new FindManager(this);
		
		this.columnDataProvider= createColumnDataProvider();
		this.rowDataProvider= createRowDataProvider();
		this.columnLabelProvider= createColumnLabelProvider();
		this.rowLabelProvider= createRowLabelProvider();
		this.sortModel= createSortModel();
	}
	
	
	public final IRDataTableInput getInput() {
		return this.input;
	}
	
	protected final AbstractRDataAdapter<T, T> getAdapter() {
		return this.adapter;
	}
	
	public final T getRObject() {
		return this.rObjectStruct;
	}
	
	final int getLockState() {
		return this.fragmentsLock.state;
	}
	
	public final void beginOperation(final Object o) {
		this.fragmentsLock.lock();
		try {
			this.activeOperations.add(o);
		}
		finally {
			this.fragmentsLock.unlock();
		}
	}
	
	public final void endOperation(final Object o) {
		this.fragmentsLock.lock();
		try {
			if (this.activeOperations.remove(o)
					&& this.activeOperations.isEmpty() ) {
				this.fragmentsLock.notifyWorker();
			}
		}
		finally {
			this.fragmentsLock.unlock();
		}
	}
	
	final void schedule(final ToolRunnable runnable) {
		try {
			final Tool tool= this.input.getTool();
			final Status status= tool.getQueue().add(runnable);
			if (status.getSeverity() == Status.ERROR && !tool.isTerminated()) {
				throw new StatusException(status);
			}
		}
		catch (final StatusException e) {
			clear(Lock.ERROR_STATE);
			logError("An error occurred when scheduling job for data viewer.", e);
		}
	}
	
	private void runInit(final RToolService r, final ProgressMonitor m) throws StatusException {
		if (this.disposeScheduled) {
			synchronized (this.initRunnable) {
				this.initScheduled= false;
			}
			return;
		}
		
		try {
			if (this.rTmpItem == null) {
//				r.evalVoid("require(\"rj\", quietly= TRUE)", m);
				this.rTmpItem= TmpUtils.newItem("viewer", r, m);
			}
		}
		catch (final Exception e) {
			synchronized (this.initRunnable) {
				this.initScheduled= false;
			}
			checkCancel(e);
			clear(Lock.ERROR_STATE);
			logError("An error occurred when preparing tmp variables for data viewer.", e);
			
			this.realm.syncExec(new Runnable() {
				@Override
				public void run() {
					for (final IDataProviderListener listener : AbstractRDataProvider.this.dataListeners.toList()) {
						listener.onInputFailed(0);
					}
				}
			});
			return;
		}
		
		try {
			final RObject rObject= (r instanceof ICombinedRDataAdapter) ?
					((ICombinedRDataAdapter) r).evalCombinedStruct(this.input.getElementName(), 0, 1, m) :
					r.evalData(this.input.getFullName(), null, RObjectFactory.F_ONLY_STRUCT, 1, m);
			if (this.rObjectStruct == null) {
				this.rObjectStruct= this.adapter.validate(rObject);
			}
			else {
				this.rObjectStruct= this.adapter.validate(rObject, this.rObjectStruct, 0);
			}
		}
		catch (final Exception e) {
			synchronized (this.initRunnable) {
				this.initScheduled= false;
			}
			checkCancel(e);
			clear(Lock.RELOAD_STATE);
			logError("An error occurred when initializing structure data for data viewer.", e);
			
			this.realm.syncExec(new Runnable() {
				@Override
				public void run() {
					for (final IDataProviderListener listener : AbstractRDataProvider.this.dataListeners.toList()) {
						listener.onInputFailed(IDataProviderListener.ERROR_STRUCT_CHANGED);
					}
				}
			});
			return;
		}
		final RDataTableContentDescription description;
		try {
			description= loadDescription(this.input.getElementName(), this.rObjectStruct, r, m);
		}
		catch (final Exception e) {
			synchronized (this.initRunnable) {
				this.initScheduled= false;
			}
			checkCancel(e);
			clear(Lock.RELOAD_STATE);
			logError("An error occurred when initializing default formats for data viewer.", e);
			return;
		}
		
		this.realm.syncExec(new Runnable() {
			@Override
			public void run() {
				AbstractRDataProvider.this.description= description;
				final long rowCount= AbstractRDataProvider.this.adapter.getRowCount(AbstractRDataProvider.this.rObjectStruct);
				final boolean rowsChanged= (rowCount != getRowCount());
				clear(0, rowCount, rowCount, true, true, true);
				
				synchronized (AbstractRDataProvider.this.initRunnable) {
					AbstractRDataProvider.this.initScheduled= false;
				}
//				if (rowsChanged) {
//					for (final IDataProviderListener listener : dataListeners) {
//						listener.onRowCountChanged();
//					}
//				}
				for (final IDataProviderListener listener : AbstractRDataProvider.this.dataListeners.toList()) {
					listener.onInputInitialized(rowsChanged);
				}
			}
		});
	}
	
	final TmpUtils.Item getTmpItem() {
		return this.rTmpItem;
	}
	
	private void runUpdate(final RToolService r, final ProgressMonitor m) throws StatusException {
		int work= -1;
		while (true) {
			try {
				final boolean updateSorting;
				final boolean updateFiltering;
				
				this.fragmentsLock.lock();
				try {
					switch (work) {
					case -1: 
						this.fragmentsLock.scheduled= false;
						break;
					case 0:
						if (!this.activeOperations.isEmpty()) {
							try {
								this.fragmentsLock.worker.await();
							}
							catch (final InterruptedException e) {}
							break;
						}
						else {
							return;
						}
					default:
						break;
					}
					work= 0;
					
					updateSorting= this.updateSorting;
					updateFiltering= this.updateFiltering;
				}
				finally {
					this.fragmentsLock.unlock();
				}
				
				FQRObjectRef elementRef= null;
				
				if (updateSorting) {
					if (elementRef == null) {
						elementRef= checkElementRef(this.input.getElementRef(), r, m);
						this.adapter.check(elementRef, this.rObjectStruct, r, m);
					}
					updateSorting(r, m);
					work++;
				}
				if (updateFiltering) {
					if (elementRef == null) {
						elementRef= checkElementRef(this.input.getElementRef(), r, m);
						this.adapter.check(elementRef, this.rObjectStruct, r, m);
					}
					updateFiltering(r, m);
					work++;
				}
				if (this.updateIdx) {
					if (elementRef == null) {
						elementRef= checkElementRef(this.input.getElementRef(), r, m);
						this.adapter.check(elementRef, this.rObjectStruct, r, m);
					}
					updateIdx(r, m);
					work++;
				}
				
				if (work == 0
						&& this.rowDataProvider instanceof AbstractRDataProvider<?>.RowDataProvider) {
					final LazyRStore<RVector<?>> namesStore= ((RowDataProvider) this.rowDataProvider).rowNamesStore;
					while (true) {
						final Fragment<RVector<?>> fragment;
						this.fragmentsLock.lock();
						try {
							fragment= namesStore.getNextScheduledFragment();
						}
						finally {
							this.fragmentsLock.unlock();
						}
						if (fragment == null) {
							break;
						}
						
						if (elementRef == null) {
							elementRef= checkElementRef(this.input.getElementRef(), r, m);
							this.adapter.check(elementRef, this.rObjectStruct, r, m);
						}
						final RVector<?> fragmentObject= this.adapter.loadRowNames(elementRef,
								this.rObjectStruct, fragment, this.rCacheIdx, r, m);
						this.fragmentsLock.lock();
						try {
							namesStore.updateFragment(fragment, fragmentObject);
							
							this.fragmentsLock.notify(fragment);
						}
						finally {
							this.fragmentsLock.unlock();
						}
						notifyListener(fragment);
						work++;
					}
				}
				if (work == 0) {
					while (true) {
						final Fragment<T> fragment;
						this.fragmentsLock.lock();
						try {
							fragment= this.dataStore.getNextScheduledFragment();
						}
						finally {
							this.fragmentsLock.unlock();
						}
						if (fragment == null) {
							break;
						}
						
						if (elementRef == null) {
							elementRef= checkElementRef(this.input.getElementRef(), r, m);
							this.adapter.check(elementRef, this.rObjectStruct, r, m);
						}
						final T fragmentObject= this.adapter.loadData(elementRef,
								this.rObjectStruct, fragment, this.rCacheIdx, r, m);
						
						this.fragmentsLock.lock();
						try {
							this.dataStore.updateFragment(fragment, fragmentObject);
							
							this.fragmentsLock.notify(fragment);
						}
						finally {
							this.fragmentsLock.unlock();
						}
						notifyListener(fragment);
						work++;
					}
				}
			}
			catch (final Exception e) {
				checkCancel(e);
				clear(Lock.RELOAD_STATE);
				logError(NLS.bind("An error occurred when loading data of ''{0}'' for data viewer.",
								this.input.getFullName()),
						e );
				return;
			}
		}
	}
	
	private FQRObjectRef checkElementRef(final FQRObjectRef elementRef,
			final RService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
		RObject env= elementRef.getEnv();
		switch (env.getRObjectType()) {
		case RObject.TYPE_REFERENCE:
			return elementRef;
		case RObject.TYPE_LANGUAGE:
			env= RDataUtils.checkRReference(
					r.evalData(((RLanguage) env).getSource(),
							null, 0, RService.DEPTH_REFERENCE, m ),
					RObject.TYPE_ENVIRONMENT );
			return new BasicFQRObjectRef(elementRef.getRHandle(), env, elementRef.getName());
		default:
			throw new UnexpectedRDataException(
					"Unexpected R object type: " + RDataUtils.getObjectTypeName(env.getRObjectType()) );
		}
	}
	
	private void updateSorting(
			final RToolService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
		cleanSorting(m);
		
		final SortColumn sortColumn;
		this.fragmentsLock.lock();
		try {
			sortColumn= this.sortColumn;
			this.updateSorting= false;
		}
		finally {
			this.fragmentsLock.unlock();
		}
		
		if (sortColumn != null) {
			if (this.rCacheSort == null) {
				this.rCacheSort= this.rTmpItem.createSub("order"); //$NON-NLS-1$
			}
			final StringBuilder cmd= getRCmdStringBuilder();
			appendOrderCmd(cmd, sortColumn);
			this.rTmpItem.set(this.rCacheSort, cmd.toString(), m);
		}
	}
	
	private void updateFiltering(
			final RToolService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
		cleanFiltering(m);
		
		String filter;
		this.fragmentsLock.lock();
		try {
			filter= this.filter;
			this.updateFiltering= false;
		}
		finally {
			this.fragmentsLock.unlock();
		}
		
		final long filteredRowCount;
		if (filter == null) {
			filteredRowCount= getFullRowCount();
		}
		else {
			if (this.rCacheFilter == null) {
				this.rCacheFilter= this.rTmpItem.createSub("include"); //$NON-NLS-1$
			}
			this.rTmpItem.set(this.rCacheFilter, filter, m);
			{	final FunctionCall call= r.createFunctionCall(RJTmp.GET_FILTERED_COUNT);
				call.addChar(RJTmp.FILTER_PAR, this.rCacheFilter);
				filteredRowCount= RDataUtils.checkSingleIntValue(call.evalData(m));
			}
		}
		this.realm.syncExec(new Runnable() {
			@Override
			public void run() {
				clear(0, filteredRowCount, getFullRowCount(), false, false, false);
				for (final IDataProviderListener listener : AbstractRDataProvider.this.dataListeners.toList()) {
					listener.onRowCountChanged();
				}
			}
		});
	}
	
	private void updateIdx(
			final RToolService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
		cleanIdx(m);
		if (this.rCacheSort != null || this.rCacheFilter != null) {
			if (this.rCacheIdx == null) {
				this.rCacheIdx= this.rTmpItem.createSub("idx"); //$NON-NLS-1$
			}
			if (this.rCacheFilter == null) { // fRCacheSort != null
				final StringBuilder cmd= getRCmdStringBuilder();
				cmd.append(TmpUtils.ENV_FQ_NAME+'$').append(this.rCacheSort);
				this.rTmpItem.set(this.rCacheIdx, cmd.toString(), m);
			}
			else if (this.rCacheSort == null) { // fRCacheFilter != null
				final FunctionCall call= r.createFunctionCall(RJTmp.SET_WHICH_INDEX);
				call.addChar(RJTmp.NAME_PAR, this.rCacheIdx);
				call.addChar(RJTmp.FILTER_PAR, this.rCacheFilter);
				call.evalVoid(m);
			}
			else { // fRCacheSort != null && fRCacheFilter != null
				final FunctionCall call= r.createFunctionCall(RJTmp.SET_FILTERED_INDEX);
				call.addChar(RJTmp.NAME_PAR, this.rCacheIdx);
				call.addChar(RJTmp.FILTER_PAR, this.rCacheFilter);
				call.addChar(RJTmp.INDEX_PAR, this.rCacheSort);
				call.evalVoid(m);
			}
		}
		this.updateIdx= false;
	}
	
	String checkFilter() {
		return this.rCacheFilter;
	}
	
	String checkRevIndex(final RToolService r, final ProgressMonitor m) throws StatusException {
		if (this.rCacheIdx != null) {
			if (this.rCacheIdxR == null) {
				final String name= this.rTmpItem.createSub("idx.r"); //$NON-NLS-1$
				try {
					final FunctionCall call= r.createFunctionCall(RJTmp.SET_REVERSE_INDEX);
					call.addChar(RJTmp.NAME_PAR, name);
					call.addChar(RJTmp.INDEX_PAR, this.rCacheIdx);
					call.addNum(RJTmp.LEN_PAR, getFullRowCount());
					call.evalVoid(m);
					return this.rCacheIdxR= name;
				}
				finally {
					if (this.rCacheIdxR == null) {
						this.rTmpItem.remove(name, m);
					}
				}
			}
			return this.rCacheIdxR;
		}
		else {
			return null;
		}
	}
	
	protected abstract RDataTableContentDescription loadDescription(RElementName name,
			T struct,
			RToolService r, ProgressMonitor m) throws StatusException, UnexpectedRDataException;
	
	
	protected RDataTableColumn createColumn(final RStore store, final String expression,
			final RElementName elementName, final long columnIndex, final String columnName,
			final RToolService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
		
		final ImList<String> classNames;
		
		RObject rObject;
		{	final FunctionCall call= r.createFunctionCall("class"); //$NON-NLS-1$
			call.add(expression);
			rObject= call.evalData(m);
			final RVector<RCharacterStore> names= RDataUtils.checkRCharVector(rObject);
			classNames= ImCollections.newList(names.getData().toArray());
		}
		RDataTableColumn column;
		final RDataFormatter format= new RDataFormatter();
		switch (store.getStoreType()) {
		case RStore.LOGICAL:
			format.setAutoWidth(5);
			column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
					IRDataTableVariable.LOGI, store, classNames, format);
			break;
		case RStore.NUMERIC:
			if (checkDateFormat(expression, classNames, format, r, m)) {
				column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
						IRDataTableVariable.DATE, store, classNames, format);
				break;
			}
			if (checkDateTimeFormat(expression, classNames, format, r, m)) {
				column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
						IRDataTableVariable.DATETIME, store, classNames, format);
				break;
			}
			{	final FunctionCall call= r.createFunctionCall("rj:::.getFormatInfo"); //$NON-NLS-1$
				call.add("x", expression); //$NON-NLS-1$
				rObject= call.evalData(m);
			}
			{	final RIntegerStore formatInfo= RDataUtils.checkRIntVector(rObject).getData();
				RDataUtils.checkLengthGreaterOrEqual(formatInfo, 3);
				format.setAutoWidth(Math.max(formatInfo.getInt(0), 3));
				format.initNumFormat(formatInfo.getInt(1), formatInfo.getInt(2) > 0 ?
						formatInfo.getInt(2) + 1 : 0);
				column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
						IRDataTableVariable.NUM, store, classNames, format);
				break;
			}
		case RStore.INTEGER:
			if (checkDateFormat(expression, classNames, format, r, m)) {
				column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
						IRDataTableVariable.DATE, store, classNames, format);
				break;
			}
			if (checkDateTimeFormat(expression, classNames, format, r, m)) {
				column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
						IRDataTableVariable.DATETIME, store, classNames, format);
				break;
			}
			{	final FunctionCall call= r.createFunctionCall("rj:::.getFormatInfo"); //$NON-NLS-1$
				call.add("x", expression); //$NON-NLS-1$
				rObject= call.evalData(m);
			}
			{	final RIntegerStore formatInfo= RDataUtils.checkRIntVector(rObject).getData();
				RDataUtils.checkLengthGreaterOrEqual(formatInfo, 1);
				format.setAutoWidth(Math.max(formatInfo.getInt(0), 3));
				column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
						IRDataTableVariable.INT, store, classNames, format);
				break;
			}
		case RStore.CHARACTER:
			{	final FunctionCall call= r.createFunctionCall("rj:::.getFormatInfo"); //$NON-NLS-1$
				call.add("x", expression); //$NON-NLS-1$
				rObject= call.evalData(m);
			}
			{	final RIntegerStore formatInfo= RDataUtils.checkRIntVector(rObject).getData();
				RDataUtils.checkLengthGreaterOrEqual(formatInfo, 1);
				format.setAutoWidth(Math.max(formatInfo.getInt(0), 3));
				column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
						IRDataTableVariable.CHAR, store, classNames, format);
				break;
			}
		case RStore.COMPLEX:
			{	final FunctionCall call= r.createFunctionCall("rj:::.getFormatInfo"); //$NON-NLS-1$
				call.add("x", expression); //$NON-NLS-1$
				rObject= call.evalData(m);
			}
			{	final RIntegerStore formatInfo= RDataUtils.checkRIntVector(rObject).getData();
				RDataUtils.checkLengthGreaterOrEqual(formatInfo, 3);
				format.setAutoWidth(Math.max(formatInfo.getInt(0), 3));
				format.initNumFormat(formatInfo.getInt(1), formatInfo.getInt(2) > 0 ?
						formatInfo.getInt(2) + 1 : 0);
				column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
						IRDataTableVariable.CPLX, store, classNames, format);
				break;
			}
		case RStore.RAW:
			format.setAutoWidth(2);
			column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
					IRDataTableVariable.RAW, store, classNames, format);
			break;
		case RStore.FACTOR:
			{	final FunctionCall call= r.createFunctionCall("levels"); //$NON-NLS-1$
				call.add(expression);
				rObject= call.evalData(m);
			}
			{	format.setAutoWidth(3);
				final RCharacterStore levels= RDataUtils.checkRCharVector(rObject).getData();
				final int l= RDataUtils.checkIntLength(levels);
				for (int i= 0; i < l; i++) {
					if (!levels.isNA(i)) {
						final int length= levels.getChar(i).length();
						if (length > format.getAutoWidth()) {
							format.setAutoWidth(length);
						}
					}
				}
				format.initFactorLevels(levels);
				column= new RDataTableColumn(columnIndex, columnName, expression, elementName,
						IRDataTableVariable.FACTOR, RFactorStructStore.addLevels((RFactorStore) store, levels),
						classNames, format);
				break;
			}
		default:
			throw new UnexpectedRDataException("store type: " + store.getStoreType());
		}
		return column;
	}
	
	protected boolean checkDateFormat(final String expression, final List<String> classNames,
			final RDataFormatter formatter,
			final RToolService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
		if (classNames.contains("Date")) { //$NON-NLS-1$
			formatter.initDateFormat(RDataFormatter.MILLIS_PER_DAY);
			formatter.setAutoWidth(10);
			return true;
		}
		return false;
	}
	
	protected boolean checkDateTimeFormat(final String expression, final List<String> classNames,
			final RDataFormatter formatter,
			final RToolService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
		RObject rObject;
		if (classNames.contains("POSIXct")) { //$NON-NLS-1$
			formatter.initDateTimeFormat(RDataFormatter.MILLIS_PER_SECOND);
			formatter.setAutoWidth(27);
			
			{	final FunctionCall call= r.createFunctionCall("base::attr"); //$NON-NLS-1$
				call.add(expression);
				call.addChar("tzone"); //$NON-NLS-1$
				rObject= call.evalData(m);
			}
			if (rObject.getRObjectType() != RObject.TYPE_NULL) {
				formatter.setDateTimeZone(TimeZone.getTimeZone(RDataUtils.checkSingleCharValue(rObject)));
			}
			return true;
		}
		return false;
	}
	
	protected RDataTableColumn createNamesColumn(final String expression, final long count,
			final RToolService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
		final RObject names= r.evalData(expression, null, RObjectFactory.F_ONLY_STRUCT, 1, m);
		if (names != null && names.getRObjectType() == RObject.TYPE_VECTOR
				&& names.getLength() == count
				&& (names.getData().getStoreType() == RStore.CHARACTER
						|| names.getData().getStoreType() == RStore.INTEGER)) {
			return createColumn(names.getData(), expression, null, -1, null, r, m);
		}
		return createAutoNamesColumn(count);
	}
	
	private RDataTableColumn createAutoNamesColumn(final long count) {
		final RDataFormatter format= new RDataFormatter();
		format.setAutoWidth(Math.max(Long.toString(count).length(), 3));
		return new RDataTableColumn(-1, null, null, null,
				IRDataTableVariable.INT, DefaultRObjectFactory.INT_STRUCT_DUMMY,
				ImCollections.newList(RObject.CLASSNAME_INTEGER),
				format);
	}
	
	protected abstract void appendOrderCmd(StringBuilder cmd, SortColumn sortColumn);
	
	
	private void runClean(final RToolService r, final ProgressMonitor m) throws StatusException {
		clear(Lock.ERROR_STATE);
		cleanSorting(m);
		cleanFiltering(m);
		this.findManager.clean(m);
		this.rTmpItem.dispose(m);
		this.rTmpItem= null;
	}
	
	private void cleanSorting(final ProgressMonitor m) throws StatusException {
		cleanIdx(m);
		if (this.rCacheSort != null) {
			this.rTmpItem.remove(this.rCacheSort, m);
			this.rCacheSort= null;
		}
	}
	
	private void cleanFiltering(final ProgressMonitor m) throws StatusException {
		cleanIdx(m);
		if (this.rCacheFilter != null) {
			this.rTmpItem.remove(this.rCacheFilter, m);
			this.rCacheFilter= null;
		}
	}
	
	private void cleanIdx(final ProgressMonitor m) throws StatusException {
		this.updateIdx= true;
		if (this.rCacheIdx != null) {
			this.rTmpItem.remove(this.rCacheIdx, m);
			this.rCacheIdx= null;
		}
		if (this.rCacheIdxR != null) {
			this.rTmpItem.remove(this.rCacheIdxR,  m);
			this.rCacheIdxR= null;
		}
	}
	
	
	protected final StringBuilder getRCmdStringBuilder() {
		this.rStringBuilder.setLength(0);
		return this.rStringBuilder;
	}
	
	
	public boolean getAllColumnsEqual() {
		return false;
	}
	
	public RDataTableContentDescription getDescription() {
		return this.description;
	}
	
	@Override
	public long getColumnCount() {
		return this.columnCount;
	}
	
	public long getFullRowCount() {
		return this.fullRowCount;
	}
	
	@Override
	public long getRowCount() {
		return this.rowCount;
	}
	
	@Override
	public Object getDataValue(final long columnIndex, final long rowIndex, final int flags,
			final IProgressMonitor monitor) {
		try {
			final LazyRStore.Fragment<T> fragment= this.fragmentsLock.getFragment(
					this.dataStore, rowIndex, columnIndex,
					flags, EStatusUtils.convert(monitor) );
			if (fragment != null) {
				return getDataValue(fragment, rowIndex, columnIndex);
			}
			else {
				return handleMissingData(flags);
			}
		}
		catch (final LoadDataException e) {
			return handleLoadDataException(e, flags);
		}
	}
	
	protected abstract Object getDataValue(LazyRStore.Fragment<T> fragment, long rowIdx, long columnIdx);
	
	@Override
	public void setDataValue(final long columnIndex, final long rowIndex, final Object newValue) {
		throw new UnsupportedOperationException();
	}
	
	protected abstract Object getColumnName(LazyRStore.Fragment<T> fragment, long columnIdx);
	
	public boolean hasRealColumns() {
		return true;
	}
	
	public boolean hasRealRows() {
		return true;
	}
	
	public IDataProvider getColumnDataProvider() {
		return this.columnDataProvider;
	}
	
	public IDataProvider getRowDataProvider() {
		return this.rowDataProvider;
	}
	
	public IDataProvider getColumnLabelProvider() {
		return this.columnLabelProvider;
	}
	
	public IDataProvider getRowLabelProvider() {
		return this.rowLabelProvider;
	}
	
	
	protected IDataProvider createColumnDataProvider() {
		return new ColumnDataProvider();
	}
	
	protected IDataProvider createRowDataProvider() {
		return new RowDataProvider();
	}
	
	protected IDataProvider createColumnLabelProvider() {
		return null;
	}
	
	protected IDataProvider createRowLabelProvider() {
		return null;
	}
	
	protected ISortModel createSortModel() {
		return new SortModel();
	}
	
	private Object handleMissingData(final int flags) {
		return ((flags & IDataProvider.FORCE_SYNC) != 0) ? ERROR : LOADING;
	}
	
	private Object handleLoadDataException(final LoadDataException e, final int flags) {
		if (!e.isRecoverable()) {
			return ERROR;
		}
		reset();
		return handleMissingData(flags);
	}
	
	
	public ISortModel getSortModel() {
		return this.sortModel;
	}
	
	public SortColumn getSortColumn() {
		return this.sortColumn;
	}
	
	private void setSortColumn(final SortColumn column) {
		this.fragmentsLock.lock();
		try {
			if (Objects.equals(this.sortColumn, column)) {
				return;
			}
			this.sortColumn= column;
			
			clear(-1, -1, -1, true, false, false);
			
			this.findManager.reset(false);
		}
		finally {
			this.fragmentsLock.unlock();
		}
	}
	
	public void setFilter(final String filter) {
		this.fragmentsLock.lock();
		try {
			if ((this.filter != null) ? this.filter.equals(filter) : null == filter) {
				return;
			}
			this.filter= filter;
			
			clear(-1, -1, -1, false, true, false);
			
			this.findManager.reset(true);
			
			this.fragmentsLock.scheduleUpdate(null, null, null, 0, null);
		}
		finally {
			this.fragmentsLock.unlock();
		}
	}
	
	public String getFilter() {
		return this.filter;
	}
	
	
	public void addFindListener(final IFindListener listener) {
		this.findManager.addFindListener(listener);
	}
	
	public void removeFindListener(final IFindListener listener) {
		this.findManager.removeFindListener(listener);
	}
	
	public void find(final FindTask task) {
		this.findManager.find(task);
	}
	
	
	public long[] toDataIdxs(final long columnIndex, final long rowIndex) {
		if (getFilter() != null || getSortColumn() != null) {
			if (this.rowDataProvider instanceof AbstractRDataProvider.RowDataProvider) {
				final long rowIdx= ((AbstractRDataProvider.RowDataProvider) this.rowDataProvider)
						.getRowIdx(rowIndex);
				return new long[] { columnIndex, rowIdx };
			}
			return new long[] { columnIndex, -2 };
		}
		return new long[] { columnIndex, rowIndex };
	}
	
	
	public void addDataChangedListener(final IDataProviderListener listener) {
		this.dataListeners.add(listener);
	}
	
	public void removeDataChangedListener(final IDataProviderListener listener) {
		this.dataListeners.remove(listener);
	}
	
	protected void notifyListener(final LazyRStore.Fragment<?> item) {
		try {
			for (final IDataProviderListener listener : this.dataListeners.toList()) {
				listener.onRowsChanged(item.getRowBeginIdx(), item.getRowEndIdx());
			}
		}
		catch (final Exception e) {
			logError("An error occurred when notifying about row updates.", e);
		}
	}
	
	
	public void reset() {
		clear(Lock.PAUSE_STATE);
		synchronized (this.initRunnable) {
			if (this.initScheduled) {
				return;
			}
			this.initScheduled= true;
		}
		try {
			final Status status= this.input.getTool().getQueue().add(this.initRunnable);
			if (status.getSeverity() >= Status.ERROR) {
				throw new StatusException(status);
			}
		}
		catch (final StatusException e) {
		}
	}
	
	private void clear(final int newState) {
		clear(newState, -1, -1, true, true, true);
	}
	
	private void clear(final int newState, final long filteredRowCount, final long fullRowCount,
			final boolean updateSorting, final boolean updateFiltering,
			final boolean clearFind) {
		this.fragmentsLock.lock();
		try {
			this.dataStore.clear(filteredRowCount);
			if (this.rowDataProvider instanceof AbstractRDataProvider<?>.RowDataProvider) {
				((RowDataProvider) this.rowDataProvider).rowNamesStore.clear(filteredRowCount);
			}
			this.updateSorting |= updateSorting;
			this.updateFiltering |= updateFiltering;
			
			if (newState >= 0 && this.fragmentsLock.state < Lock.ERROR_STATE) {
				this.fragmentsLock.state= newState;
			}
			this.fragmentsLock.clear();
			
			if (filteredRowCount >= 0) {
				this.rowCount= filteredRowCount;
				this.fullRowCount= fullRowCount;
			}
			
			if (clearFind) {
				this.findManager.clear(newState);
			}
		}
		finally {
			this.fragmentsLock.unlock();
		}
	}
	
	public void dispose() {
		this.disposeScheduled= true;
		schedule(this.cleanRunnable);
	}
	
}
