package ru.ydn.wicket.wicketorientdb.model;

import java.io.Serializable;
import java.util.Iterator;

import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;

import com.google.common.base.Function;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.type.ODocumentWrapper;

/**
 * Provider of data by quering of OrientDB
 * @param <K>
 */
public class OQueryDataProvider <K> extends SortableDataProvider<K, String>
{
	private static final long serialVersionUID = 1L;
	private OQueryModel<K> model;
	
	/**
	 * @param sql SQL to be executed to obtain data
	 */
	public OQueryDataProvider(String sql)
	{
		model = new OQueryModel<K>(sql);
	}
	/**
	 * @param sql SQL to be executed to obtain data
	 * @param transformer transformer for wrapping of {@link ODocument} ot required type
	 */
	public OQueryDataProvider(String sql, Function<?, K> transformer)
	{
		model = new OQueryModel<K>(sql, transformer);
	}
	/**
	 * @param sql SQL to be executed to obtain data
	 * @param wrapperClass target type for wrapping of {@link ODocument}
	 */
    public OQueryDataProvider(String sql, Class<? extends K> wrapperClass)
    {
        model = new OQueryModel<K>(sql, wrapperClass);
    }

    /**
     * Set value for named parameter
     * @param paramName name of the parameter to set
     * @param value {@link IModel} for the parameter value
     * @return this {@link OQueryDataProvider}
     */
    public OQueryDataProvider<K> setParameter(String paramName, IModel<?> value)
    {
        model.setParameter(paramName, value);
        return this;
    }

    @Override
    public Iterator<K> iterator(long first, long count)
    {
        SortParam<String> sort = getSort();
        if(sort!=null)
        {
            model.setSortableParameter(sort.getProperty());
            model.setAccessing(sort.isAscending());
        }
        return (Iterator<K>)model.iterator(first, count);        
    }
    
    public OClass probeOClass(int probeLimit) {
    	return model.probeOClass(probeLimit);
    }

    @SuppressWarnings("unchecked")
	public IModel<K> model(K o)
    {
    	return ModelUtils.model(o);
    }
    
    /**
     * Set sort
     * @param property property to sort on
     * @param order order to apply: true is for ascending, false is for descending
     */
    public void setSort(String property, Boolean order) {
    	SortOrder sortOrder = order==null?SortOrder.ASCENDING:(order?SortOrder.ASCENDING:SortOrder.DESCENDING);
    	if(property==null) {
    		if(order==null) setSort(null);
    		else setSort("@rid", sortOrder);
    	} else {
    		super.setSort(property, sortOrder);
    	}
    }

    @Override
    public long size()
    {
        return model.size();
    }

    @Override
    public void detach()
    {
        model.detach();
        super.detach();        
    }
}
@@ -1016,32 +1016,29 @@
 g sql)%0A%09%7B%0A%09%09
-model = 
+this(
 new OQueryMo
@@ -1048,16 +1048,17 @@
 %3CK%3E(sql)
+)
 ;%0A%09%7D%0A%09/*
@@ -1271,24 +1271,21 @@
 r)%0A%09%7B%0A%09%09
-model = 
+this(
 new OQue
@@ -1312,16 +1312,17 @@
 sformer)
+)
 ;%0A%09%7D%0A%09/*
@@ -1540,16 +1540,13 @@
     
-model = 
+this(
 new 
@@ -1578,16 +1578,265 @@
 erClass)
+);%0A    %7D%0A    %0A    /**%0A     * Low level constructor to initialize by direct %7B@link OQueryModel%7D%0A     * @param oQueryModel %7B@link OQueryModel%7D to use in provider%0A     */%0A    public OQueryDataProvider(OQueryModel%3CK%3E model)%0A    %7B%0A    %09this.model = model
 ;%0A    %7D%0A

Allow to provide OQueryModel directly to OQueryProvider