package org.orienteer.core.model;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;

import ru.ydn.wicket.wicketorientdb.proto.IPrototype;

import com.orientechnologies.orient.core.metadata.schema.OProperty;
import com.orientechnologies.orient.core.metadata.schema.OType;

/**
 * Dynamic {@link IModel}&lt;{@link List}&lt; {@link OType} &gt;&gt; 
 * to get {@link OType}s to which current {@link OType} can be switched to 
 */
public class ListAvailableOTypesModel extends LoadableDetachableModel<List<OType>>
{
	private final IModel<OProperty> propertyModel;
	private final static List<OType> WHOLE_LIST = orderTypes(Arrays.asList(OType.values()));
	private final static Map<OType, List<OType>> CACHE_ORDERED = new HashMap<OType, List<OType>>();
	
	public ListAvailableOTypesModel(IModel<OProperty> propertyModel)
	{
		this.propertyModel = propertyModel;
	}
	
	@Override
	protected List<OType> load() {
		OProperty property = propertyModel.getObject();
		
		return property==null || property instanceof IPrototype? findAvailableOTypes(null) : findAvailableOTypes(property.getType());
	}
	
	protected List<OType> findAvailableOTypes(OType type)
	{
		if(type==null) return WHOLE_LIST;
		else
		{
			List<OType> ret = CACHE_ORDERED.get(type);
			if(ret==null)
			{
				ret = orderTypes(type.getCastable());
				CACHE_ORDERED.put(type, ret);
			}
			return ret;
		}
	}
	
	public static List<OType> orderTypes(Collection<OType> types)
	{
		List<OType> list = types instanceof List?(List<OType>)types:new ArrayList<OType>(types);
		
		Collections.sort(list, new Comparator<OType>() {

			@Override
			public int compare(OType o1, OType o2) {
				return o1.name().compareTo(o2.name());
			}
		});
		return list;
	}

	@Override
	protected void onDetach() {
		super.onDetach();
		propertyModel.detach();
	}
	
	
	
	
}

@@ -1523,43 +1523,189 @@
 %09%09%09%09
-ret = orderTypes(type.getCastable()
+List%3COType%3E candidates = new ArrayList%3C%3E(Arrays.asList(OType.values()));%0A%09%09%09%09candidates.removeIf(candidate-%3E!candidate.getCastable().contains(type));%0A%09%09%09%09ret = orderTypes(candidates
 );%0A%09
@@ -1923,19 +1923,16 @@
 types);%0A
-%09%09%0A
 %09%09Collec
@@ -1952,103 +1952,24 @@
 st, 
-new Comparator%3COType%3E() %7B%0A%0A%09%09%09@Override%0A%09%09%09public int compare(OType o1, OType o2) %7B%0A%09%09%09%09return 
+%0A%09%09%09%09(o1, o2) -%3E
 o1.n
@@ -1998,18 +1998,8 @@
 e())
-;%0A%09%09%09%7D%0A%09%09%7D
 );%0A%09

Fix #700: available list of property types to change to is not correct