/**
 * Copyright (c) 2006, yher2.net
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright notice, 
 *   this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright notice, 
 *   this list of conditions and the following disclaimer in the documentation 
 *   and/or other materials provided with the distribution.
 * * Neither the name of the nor the names of its contributors may be used to endorse or 
 *   promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE.
 */
package net.yher2.workstyle.manager;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

import net.yher2.workstyle.exception.DuplicateException;
import net.yher2.workstyle.exception.NotFoundException;
import net.yher2.workstyle.torque.Tag;
import net.yher2.workstyle.torque.TagPeer;
import net.yher2.workstyle.torque.TagType;
import net.yher2.workstyle.torque.TagTypePeer;
import net.yher2.workstyle.torque.Task;
import net.yher2.workstyle.torque.TaskPeer;
import net.yher2.workstyle.torque.bean.TagBean;

import org.apache.torque.TorqueException;
import org.apache.torque.util.Criteria;

public class TagManager {
	private Connection con = null;
	
	public TagManager(Connection con) {
		this.con = con;
	}
	public TagBean add(String tag) throws DuplicateException, TorqueException {
		if (TagPeer.doSelectByName(tag, con).size() > 0) throw new DuplicateException("タグ("+tag+")");
		
		Tag dbTag = insertTag(tag);
		try {
			return get(dbTag.getTagId());
		} catch (NotFoundException e) {
			throw new TorqueException(e);
		}
	}
	private Tag insertTag(String tag) throws TorqueException {
		Tag dbTag = new Tag();
		dbTag.setActive(Tag.ACTIVE);
		dbTag.setName(tag);
		dbTag.setTagTypeId(TagType.DEFAULT_ID);
		
		TagPeer.doInsert(dbTag, con);
		return dbTag;
	}
	protected TagBean addIfNotExist(String tag) throws TorqueException {
		List<Tag> exist = TagPeer.doSelectByName(tag, con);
		Tag dbTag = null;
		if (exist.size() > 0) {
			dbTag = exist.get(0);
		} else {
			dbTag = insertTag(tag);
		}
		try {
			return get(dbTag.getTagId());
		} catch (NotFoundException e) {
			throw new TorqueException(e);
		}
	}
	protected void add(List<String> tagList) throws TorqueException {
		if (tagList.size() == 0) return;
		List<Tag> dbTagList = TagPeer.doSelectByName(tagList, con);
		for (Tag tag : dbTagList) {
			tagList.remove(tag.getName());
		}
		for (String tagName : tagList) {
			insertTag(tagName);
		}
	}
	
	public TagBean updateType(int tagId, int tagTypeId) throws TorqueException, NotFoundException {
		Tag tag = getDBModel(tagId);
		TagType tagType = new TagTypeManager(con).getDBModel(tagTypeId);
		
		tag.setTagType(tagType);
		TagPeer.doUpdate(tag, con);
		return tag.getBean();
	}
	
	public TagBean toggleActivity(int tagId) throws TorqueException, NotFoundException {
		Tag tag = getDBModel(tagId);
		if (tag.getActive() == Tag.ACTIVE) {
			tag.setActive(Tag.INACTIVE);
		} else {
			tag.setActive(Tag.ACTIVE);
		}
		TagPeer.doUpdate(tag, con);
		return tag.getBean();
	}
	
	public List<TagBean> list() throws TorqueException {
		Criteria criteria = new Criteria();
		criteria.addJoin(TagPeer.TAG_TYPE_ID, TagTypePeer.TAG_TYPE_ID);
		criteria.add(TagPeer.ACTIVE, Tag.ACTIVE);
		criteria.addAscendingOrderByColumn(TagTypePeer.SORT_ORDER);
		criteria.addAscendingOrderByColumn(TagTypePeer.NAME);
		criteria.addAscendingOrderByColumn(TagPeer.NAME);
		
		return list(criteria);
	}
	public List<TagBean> listAll() throws TorqueException {
		Criteria criteria = new Criteria();
		criteria.addJoin(TagPeer.TAG_TYPE_ID, TagTypePeer.TAG_TYPE_ID);
		criteria.addAscendingOrderByColumn(TagTypePeer.SORT_ORDER);
		criteria.addAscendingOrderByColumn(TagTypePeer.NAME);
		criteria.addAscendingOrderByColumn(TagPeer.NAME);
		
		return list(criteria);
	}
	private List<TagBean> list(Criteria criteria) throws TorqueException {
		List<Tag> dbTagList = TagPeer.doSelectJoinTagType(criteria, con);
		List<TagBean> beanList = new ArrayList<TagBean>();
		for (Tag tag : dbTagList) {
			beanList.add(tag.getBean());
		}
		return beanList;
	}
	
	public TagBean delete(int tagId) throws TorqueException, NotFoundException {
		Tag tag = getDBModel(tagId);
		
		Criteria criteria = new Criteria();
		String tagKey = "%" + Tag.format(tag.getName()) + "%";
		criteria.add(TaskPeer.TAG_LIST, (Object)tagKey, Criteria.LIKE);
		List<Task> taskList = TaskPeer.doSelect(criteria, con);
		
		tagKey = Tag.formatRegExp(tag.getName());
		for (Task task : taskList) {
			task.setTagList(task.getTagList().replaceAll(tagKey, ""));
			TaskPeer.doUpdate(task, con);
		}
		TagPeer.doDelete(tag.getPrimaryKey(), con);
		return tag.getBean();
	}
	public TagBean get(int tagId) throws TorqueException, NotFoundException {
		return getDBModel(tagId).getBean();
	}
	private Tag getDBModel(int tagId) throws TorqueException, NotFoundException {
		Criteria criteria = new Criteria();
		criteria.addJoin(TagPeer.TAG_TYPE_ID, TagTypePeer.TAG_TYPE_ID);
		criteria.add(TagPeer.TAG_ID, tagId);
		List<Tag> list = TagPeer.doSelectJoinTagType(criteria, con);
		if (list.size() == 0) throw new NotFoundException("指定のタグ("+tagId+")");
		return list.get(0);
	}
}
