package org.bench4q.master.domain.factory;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.xml.bind.JAXBException;

import org.apache.log4j.Logger;
import org.bench4q.master.domain.entity.plugin.BehaviorInfo;
import org.bench4q.master.domain.entity.plugin.CheckBoxType;
import org.bench4q.master.domain.entity.plugin.ChoiceType;
import org.bench4q.master.domain.entity.plugin.ComboType;
import org.bench4q.master.domain.entity.plugin.DateType;
import org.bench4q.master.domain.entity.plugin.FieldType;
import org.bench4q.master.domain.entity.plugin.FileType;
import org.bench4q.master.domain.entity.plugin.Group;
import org.bench4q.master.domain.entity.plugin.NFieldType;
import org.bench4q.master.domain.entity.plugin.ParamInfo;
import org.bench4q.master.domain.entity.plugin.ParamType;
import org.bench4q.master.domain.entity.plugin.PluginInfo;
import org.bench4q.master.domain.entity.plugin.PluginUI;
import org.bench4q.master.domain.entity.plugin.RadioButtonType;
import org.bench4q.master.domain.entity.plugin.SelectType;
import org.bench4q.master.domain.entity.plugin.TableType;
import org.bench4q.master.exception.ExceptionLog;
import org.bench4q.share.models.master.plugin.BehaviorInfoModel;
import org.bench4q.share.models.master.plugin.CheckBoxModel;
import org.bench4q.share.models.master.plugin.ChoiceModel;
import org.bench4q.share.models.master.plugin.ComboModel;
import org.bench4q.share.models.master.plugin.DateModel;
import org.bench4q.share.models.master.plugin.FieldModel;
import org.bench4q.share.models.master.plugin.FileModel;
import org.bench4q.share.models.master.plugin.GroupModel;
import org.bench4q.share.models.master.plugin.NFieldModel;
import org.bench4q.share.models.master.plugin.ParamInfoModel;
import org.bench4q.share.models.master.plugin.ParamTypeModel;
import org.bench4q.share.models.master.plugin.PluginInfoModel;
import org.bench4q.share.models.master.plugin.PluginUIModel;
import org.bench4q.share.models.master.plugin.RadioButtonModel;
import org.bench4q.share.models.master.plugin.SelectModel;
import org.bench4q.share.models.master.plugin.TableModel;
import org.springframework.stereotype.Component;

@Component
public class PluginDomainFactory {

	private Logger logger = Logger.getLogger(PluginDomainFactory.class);

	public PluginUIModel createPluginUIModelwithOutBehaviors(PluginUI pluginUI) {
		if (pluginUI == null || pluginUI.getPluginInfo() == null
				|| pluginUI.getBehaviorInfos() == null) {
			return null;
		}
		PluginUIModel pluginUIModel = new PluginUIModel();
		pluginUIModel.setPluginInfoModel(createPluginInfoModel(pluginUI
				.getPluginInfo()));
		pluginUIModel.setCreateTimeDate(pluginUI.getCreateDateTime());
		return pluginUIModel;
	}

	private PluginInfoModel createPluginInfoModel(PluginInfo pluginInfo) {
		PluginInfoModel pluginInfoModel = new PluginInfoModel();
		pluginInfoModel.setName(pluginInfo.getName());
		pluginInfoModel.setParamInfoModels(createParamInfoModels(pluginInfo
				.getParams()));
		pluginInfoModel
				.setGroupModels(createGroupModels(pluginInfo.getGroups()));
		return pluginInfoModel;
	}

	public List<BehaviorInfoModel> createBehaviorInfoModels(
			Set<BehaviorInfo> behaviorInfos) {
		List<BehaviorInfoModel> behaviorInfoModels = new LinkedList<BehaviorInfoModel>();
		for (BehaviorInfo behaviorInfo : behaviorInfos) {
			behaviorInfoModels.add(createBehaviorInfoModel(behaviorInfo));
		}
		return behaviorInfoModels;
	}

	private BehaviorInfoModel createBehaviorInfoModel(BehaviorInfo behaviorInfo) {
		BehaviorInfoModel behaviorInfoModel = new BehaviorInfoModel();
		behaviorInfoModel.setName(behaviorInfo.getName());
		behaviorInfoModel.setParamInfoModels(createParamInfoModels(behaviorInfo
				.getParams()));
		behaviorInfoModel.setGroupModels(createGroupModels(behaviorInfo
				.getGroups()));
		return behaviorInfoModel;

	}

	private ParamInfoModel createParamInfoModel(ParamInfo paramInfo) {
		ParamInfoModel paramInfoModel = new ParamInfoModel();
		paramInfoModel.setLabel(paramInfo.getLable());
		paramInfoModel.setName(paramInfo.getName());
		paramInfoModel.setRequired(paramInfo.getRequired());
		try {

			ParamTypeModelFactory paramTypeModelFactory = new ParamTypeModelFactory();
			paramInfoModel.setParamTypeModel(paramTypeModelFactory
					.createParamModel(paramInfo));

		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			logger.info(ExceptionLog.getStackTrace(e));
			return null;
		}
		return paramInfoModel;
	}

	private List<ParamInfoModel> createParamInfoModels(
			Set<? extends ParamInfo> paramInfos) {
		if (paramInfos == null) {
			return null;
		}
		List<ParamInfoModel> paramInfoModels = new LinkedList<ParamInfoModel>();
		for (ParamInfo paramInfo : paramInfos) {
			ParamInfoModel paramInfoModel = createParamInfoModel(paramInfo);
			if (paramInfo == null) {
				return null;
			}
			paramInfoModels.add(paramInfoModel);
		}

		return paramInfoModels;
	}

	private List<GroupModel> createGroupModels(Set<Group> groups) {
		if (groups == null) {
			return null;
		}
		List<GroupModel> groupModels = new LinkedList<GroupModel>();
		for (Group group : groups) {
			groupModels.add(createGroupModel(group));
		}
		return groupModels;
	}

	private GroupModel createGroupModel(Group group) {
		if (group == null) {
			return null;
		}
		GroupModel groupModel = new GroupModel();
		groupModel.setName(group.getName());
		groupModel.setParamInfoModels(createParamInfoModels(group.getParams()));
		return groupModel;

	}

}

@Component
class ParamTypeModelFactory {

	public ParamTypeModel createParamModel(ParamInfo paramInfo)
			throws JAXBException {
		ParamType paramType = paramInfo.getParamType();
		ParamTypeModel paramTypeModel = null;
		if (paramType instanceof FieldType) {
			paramTypeModel = createFieldModel((FieldType) paramType);
		}

		else if (paramType instanceof NFieldType) {
			paramTypeModel = createNFieldModel((NFieldType) paramType);
		} else if (paramType instanceof TableType) {
			paramTypeModel = createTableModel((TableType) paramType);
		} else if (paramType instanceof CheckBoxType) {
			paramTypeModel = createCheckBoxModel((CheckBoxType) paramType);
		} else if (paramType instanceof ComboType) {
			paramTypeModel = createComboModel((ComboType) paramType);
		} else if (paramType instanceof RadioButtonType) {
			paramTypeModel = createRadioButton((RadioButtonType) paramType);
		} else if (paramType instanceof FileType) {
			paramTypeModel = createFileModel((FileType) paramType);

		} else if (paramType instanceof DateType) {
			paramTypeModel = createDateModel((DateType) paramType);
		} else if (paramType instanceof SelectType) {
			paramTypeModel = createSelectModel((SelectType) paramType);

		} else {
			Logger.getLogger(ParamTypeModelFactory.class).info(
					"invalidated paramtype");
		}
		paramTypeModel.setType(paramType.getType());
		return paramTypeModel;
	}

	private FieldModel createFieldModel(FieldType fieldType) {
		FieldModel fieldModel = new FieldModel();
		fieldModel.setSize(fieldType.getSize());
		fieldModel.setText(fieldType.getText());
		return fieldModel;

	}

	private NFieldModel createNFieldModel(NFieldType nFieldType) {
		NFieldModel nFieldModel = new NFieldModel();
		nFieldModel.setSize(nFieldType.getSize());
		nFieldModel.setText(nFieldType.getText());
		return nFieldModel;

	}

	private TableModel createTableModel(TableType tableType) {
		TableModel tableModel = new TableModel();
		tableModel.setCols(tableType.getCols());
		return tableModel;
	}

	private CheckBoxModel createCheckBoxModel(CheckBoxType checkBoxType) {
		CheckBoxModel checkBoxModel = new CheckBoxModel();
		checkBoxModel.setChoiceModels(createChoiceModels(checkBoxType
				.getChoiceList()));
		return checkBoxModel;

	}

	private ComboModel createComboModel(ComboType comboType) {
		ComboModel comboModel = new ComboModel();
		comboModel
				.setChoiceModels(createChoiceModels(comboType.getChoiceList()));
		return comboModel;
	}

	private RadioButtonModel createRadioButton(RadioButtonType radioButtonType) {
		RadioButtonModel radioButtonModel = new RadioButtonModel();
		radioButtonModel.setChoiceModels(createChoiceModels(radioButtonType
				.getChoices()));
		return radioButtonModel;

	}

	private FileModel createFileModel(FileType fileType) {
		FileModel fileModel = new FileModel();
		fileModel.setText(fileType.getText());
		return fileModel;

	}

	private List<ChoiceModel> createChoiceModels(List<ChoiceType> choiceTypes) {
		List<ChoiceModel> choiceModels = new LinkedList<ChoiceModel>();
		for (ChoiceType choiceType : choiceTypes) {
			choiceModels.add(createChoiceModel(choiceType));
		}
		return choiceModels;
	}

	private ChoiceModel createChoiceModel(ChoiceType choiceType) {
		ChoiceModel choiceModel = new ChoiceModel();
		choiceModel.setDefaultValue(choiceType.isDefaultValue());
		choiceModel.setValue(choiceType.getValue());
		return choiceModel;

	}

	private DateModel createDateModel(DateType dateType) {
		DateModel dateModel = new DateModel();
		dateModel.setSize(dateType.getSize());
		dateModel.setType("date");
		return dateModel;
	}

	private SelectModel createSelectModel(SelectType selectType) {
		SelectModel selectModel = new SelectModel();
		selectModel.setSize(selectType.getSize());
		selectModel.setOptions(selectType.getOptions());
		selectModel.setType("select");
		return selectModel;

	}
}