package storybook.ui.dialog.decorator;

import com.googlecode.genericdao.search.Search;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import org.hibernate.Session;
import api.mig.swing.MigLayout;
import storybook.model.Model;
import storybook.model.handler.AbstractEntityHandler;
import storybook.model.hbn.dao.ItemDAO;
import storybook.model.hbn.dao.PersonDAO;
import storybook.model.hbn.dao._GenericDAO;
import storybook.model.hbn.entity.AbstractEntity;
import storybook.model.hbn.entity.Item;
import storybook.model.hbn.entity.Person;
import storybook.ui.MainFrame;
import storybook.ui.interfaces.IRefreshable;
import storybook.ui.panel.AbstractPanel;

@SuppressWarnings("serial")
public class CheckBoxPanel extends AbstractPanel implements IRefreshable {

	public final Map<AbstractEntity, JCheckBox> cbMap;
	private CbPanelDecorator decorator;
	private AbstractEntity entity;
	public AbstractEntityHandler entityHandler;
	public List<AbstractEntity> entities;
	private Search search;
	public boolean autoSelect = true;
	private AbstractEntity pointedEntity;

	public CheckBoxPanel(MainFrame mainFrame) {
		this.mainFrame = mainFrame;
		cbMap = new TreeMap<>();
	}

	@Override
	public void modelPropertyChange(PropertyChangeEvent evt) {
		// empty
	}

	@SuppressWarnings("unchecked")
	@Override
	public void init() {
		cbMap.clear();
		List<AbstractEntity> allEntities;
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		_GenericDAO<?, ?> dao = entityHandler.createDAO();
		dao.setSession(session);
		if (search != null) {
			if (search.toString().equals(Person.class.toString())) {
				allEntities = loadPersons();
			} else if (search.toString().equals(Item.class.toString())) {
				allEntities = loadItems();
			} else {
				allEntities = dao.search(search);
			}
		} else {
			allEntities = (List<AbstractEntity>) dao.findAll();
		}
		for (AbstractEntity entity2 : allEntities) {
			addEntity(entity2);
		}
		refresh();
		// refresh entities, must be before selectEntity()
		if (entities != null) {
			for (AbstractEntity ent : entities) {
				session.refresh(ent);
			}
			if (autoSelect) {
				for (AbstractEntity ent : entities) {
					selectEntity(ent);
				}
			}
		}
		model.commit();
	}

	@Override
	public void initUi() {
		setLayout(new MigLayout("wrap"));
		//setBackground(Color.white);
		refresh();
	}

	@Override
	public void refresh() {
		removeAll();
		if (decorator != null) {
			decorator.decorateBeforeFirstEntity();
		}
		Iterator<Entry<AbstractEntity, JCheckBox>> it = cbMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<AbstractEntity, JCheckBox> pairs = (Map.Entry<AbstractEntity, JCheckBox>) it.next();
			AbstractEntity ent = pairs.getKey();
			if (decorator != null) {
				decorator.decorateBeforeEntity(ent);
				decorator.decorateEntity(pairs.getValue(), ent);
			} else {
				add(pairs.getValue(), "split 2");
				add(new JLabel(ent.getIcon()));
			}
			if (decorator != null) {
				decorator.decorateAfterEntity(ent);
			}
		}
		revalidate();
		repaint();
	}

	public void selectEntities(List<?> entities) {
		for (Object ent : entities) {
			JCheckBox cb = cbMap.get((AbstractEntity) ent);
			if (cb != null) {
				cb.setSelected(true);
			}
		}
	}

	public void selectEntity(AbstractEntity ent) {
		JCheckBox cb = cbMap.get(ent);
		if (cb != null) {
			cb.setSelected(true);
		}
	}

	public List<AbstractEntity> getSelectedEntities() {
		List<AbstractEntity> ret = new ArrayList<>();
		Iterator<Entry<AbstractEntity, JCheckBox>> it = cbMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<AbstractEntity, JCheckBox> pairs = (Map.Entry<AbstractEntity, JCheckBox>) it.next();
			JCheckBox cb = pairs.getValue();
			if (cb.isSelected()) {
				ret.add(pairs.getKey());
			}
		}
		return ret;
	}

	public void addEntities(List<AbstractEntity> entities) {
		for (AbstractEntity e : entities) {
			addEntity(e);
		}
	}

	public void addEntity(AbstractEntity entity) {
		JCheckBox ck = new JCheckBox();
		ck.setOpaque(false);
		ck.addActionListener(evt -> pointedEntity = entity);
		cbMap.put(entity, ck);
		ck.setText(entity.toString());
		add(ck);
		add(new JLabel(entity.getIcon()));
	}

	public AbstractEntity getPointedEntity() {
		return (pointedEntity);
	}

	public CbPanelDecorator getDecorator() {
		return decorator;
	}

	public void setDecorator(CbPanelDecorator decorator) {
		this.decorator = decorator;
	}

	@Override
	public MainFrame getMainFrame() {
		return mainFrame;
	}

	public AbstractEntity getEntity() {
		return entity;
	}

	public void setEntity(AbstractEntity entity) {
		this.entity = entity;
	}

	public AbstractEntityHandler getEntityHandler() {
		return entityHandler;
	}

	public void setEntityHandler(AbstractEntityHandler entityHandler) {
		this.entityHandler = entityHandler;
	}

	public void setEntityList(List<AbstractEntity> entities) {
		this.entities = entities;
	}

	public Search getSearch() {
		return search;
	}

	public void setSearch(Search search) {
		this.search = search;
	}

	public boolean getAutoSelect() {
		return autoSelect;
	}

	public void setAutoSelect(boolean flag) {
		this.autoSelect = flag;
	}

	@SuppressWarnings("unchecked")
	private List<AbstractEntity> loadPersons() {
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		PersonDAO dao = new PersonDAO(session);
		return ((List) dao.findAllByCategory());
	}

	private List<AbstractEntity> loadItems() {
		Model model = mainFrame.getBookModel();
		Session session = model.beginTransaction();
		ItemDAO dao = new ItemDAO(session);
		List<AbstractEntity> items = dao.findAllByCategory();
		return (items);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// empty
	}

}
