package net.w_horse.excelpojo.excel.cellseeker;

import java.lang.annotation.Annotation;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

import net.w_horse.excelpojo.annotation.ConstantValue;
import net.w_horse.excelpojo.annotation.HorizontalRepeats;
import net.w_horse.excelpojo.annotation.LabeledCell;
import net.w_horse.excelpojo.annotation.MappedCell;
import net.w_horse.excelpojo.annotation.PointedCell;
import net.w_horse.excelpojo.annotation.VerticalRepeats;
import net.w_horse.excelpojo.xml.AbstractCellSeekerFactoryBean;
import net.w_horse.excelpojo.xml.ConstantValueCellSeekerFactoryBean;
import net.w_horse.excelpojo.xml.HorizontalRepeatsSeekerFactoryBean;
import net.w_horse.excelpojo.xml.LabeledCellSeekerFactoryBean;
import net.w_horse.excelpojo.xml.MappedCellSeekerFactoryBean;
import net.w_horse.excelpojo.xml.PointedCellSeekerFactoryBean;
import net.w_horse.excelpojo.xml.VerticalRepeatsSeekerFactoryBean;
import net.w_horse.excelpojo.xml.tag.RetrieveType;

public class CellSeekerManager {
	private static CellSeekerManager instance;
	private Map<RetrieveType, Class<? extends AbstractCellSeekerFactoryBean>> cellSeekerFactoryBeanMap = new EnumMap<RetrieveType, Class<? extends AbstractCellSeekerFactoryBean>>(RetrieveType.class);
	private Map<Class<? extends Annotation>, Class<? extends CellSeeker>> cellSeekerAnnotationMap = new HashMap<Class<? extends Annotation>, Class<? extends CellSeeker>>();

	private static CellSeekerManager getInstance() {
		if (instance == null) {
			instance = new CellSeekerManager();
		}
		return instance;
	}

	private CellSeekerManager() {
		// RetrieveType と AbstractCellSeekerFactoryBeanのマッピングの初期化
		cellSeekerFactoryBeanMap.put(RetrieveType.CONSTANT_VALUE, ConstantValueCellSeekerFactoryBean.class);
		cellSeekerFactoryBeanMap.put(RetrieveType.HORIZONTAL_REPEATS, HorizontalRepeatsSeekerFactoryBean.class);
		cellSeekerFactoryBeanMap.put(RetrieveType.LABELED_CELL, LabeledCellSeekerFactoryBean.class);
		cellSeekerFactoryBeanMap.put(RetrieveType.MAPPED_CELL, MappedCellSeekerFactoryBean.class);
		cellSeekerFactoryBeanMap.put(RetrieveType.POINTED_CELL, PointedCellSeekerFactoryBean.class);
		cellSeekerFactoryBeanMap.put(RetrieveType.VERTICAL_REPEATS, VerticalRepeatsSeekerFactoryBean.class);

		// アノテーション と CellSeekerのマッピングの初期化
		cellSeekerAnnotationMap.put(ConstantValue.class, ConstantValueCellSeeker.class);
		cellSeekerAnnotationMap.put(HorizontalRepeats.class, HorizontalRepeatsSeeker.class);
		cellSeekerAnnotationMap.put(LabeledCell.class, LabeledCellSeeker.class);
		cellSeekerAnnotationMap.put(MappedCell.class, MappedCellSeeker.class);
		cellSeekerAnnotationMap.put(PointedCell.class, PointedCellSeeker.class);
		cellSeekerAnnotationMap.put(VerticalRepeats.class, VerticalRepeatsSeeker.class);
	}

	public static AbstractCellSeekerFactoryBean getCellSeekerFactoryBeanInstance(RetrieveType retrieveType) throws InstantiationException, IllegalAccessException {
		Class<? extends AbstractCellSeekerFactoryBean> cellSeekerFactoryBeanClass
			= getInstance().cellSeekerFactoryBeanMap.get(retrieveType);
		return (cellSeekerFactoryBeanClass != null ? cellSeekerFactoryBeanClass.newInstance() : null);
	}

	public static CellSeeker getCellSeekerInstance(Annotation annotation) throws InstantiationException, IllegalAccessException {
		Class<? extends CellSeeker> cellSeekerClass = getInstance().cellSeekerAnnotationMap.get(annotation.annotationType());
		return (cellSeekerClass != null ? cellSeekerClass.newInstance() : null);
	}
}
