/*
 * This file is part of NeighborNote
 * Copyright 2013 Yuki Takahashi
 * 
 * This file may be licensed under the terms of of the
 * GNU General Public License Version 2 (the ``GPL'').
 *
 * Software distributed under the License is distributed
 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
 * express or implied. See the GPL for the specific language
 * governing rights and limitations.
 *
 * You should have received a copy of the GPL along with this
 * program. If not, go to http://www.gnu.org/licenses/gpl.html
 * or write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
*/

package cx.fbn.nevernote.gui;

import java.util.ArrayList;
import java.util.List;

import com.trolltech.qt.core.QPoint;
import com.trolltech.qt.core.QSize;
import com.trolltech.qt.core.Qt;
import com.trolltech.qt.gui.QAction;
import com.trolltech.qt.gui.QActionGroup;
import com.trolltech.qt.gui.QCursor;
import com.trolltech.qt.gui.QFocusEvent;
import com.trolltech.qt.gui.QIcon;
import com.trolltech.qt.gui.QLineEdit;
import com.trolltech.qt.gui.QMenu;
import com.trolltech.qt.gui.QPixmap;
import com.trolltech.qt.gui.QResizeEvent;
import com.trolltech.qt.gui.QStyle.PixelMetric;
import com.trolltech.qt.gui.QToolButton;

import cx.fbn.nevernote.Global;
import cx.fbn.nevernote.sql.DatabaseConnection;

public class SearchEdit extends QLineEdit {
	private final SearchClearButton clearButton;
	private final QToolButton targetButton;
	private final String inactiveColor;
	private final String activeColor;
	private String defaultText;
	private final QMenu targetMenu;
	private final QAction allNotesAction;
	private final QAction currentContextAction;
	private String targetStackName;
	private String targetNotebookGuid;
	private final List<String> targetTagGuids;
	private final DatabaseConnection conn;
	
	public enum SearchTarget {AllNotes, CurrentContext};

	
	public SearchEdit(String iconPath, DatabaseConnection conn) {
		this.conn = conn;
		
		inactiveColor = new String("QLineEdit {color: gray; font:italic;} ");
		activeColor = new String("QLineEdit {color: black; font:normal;} ");
		
		targetStackName = new String("");
		targetNotebookGuid = new String("");
		targetTagGuids = new ArrayList<String>();
		
		this.clearButton = new SearchClearButton(this, iconPath);
		this.clearButton.clicked.connect(this, "clear()");
		
		this.targetButton = new QToolButton(this);
		QPixmap targetIcon = new QPixmap(iconPath + "searchTarget.png");
		this.targetButton.setIcon(new QIcon(targetIcon));
		this.targetButton.setIconSize(new QSize(24, 16));
		this.targetButton.setCursor(new QCursor(Qt.CursorShape.ArrowCursor));
		this.targetButton.setStyleSheet("QToolButton { background-color: #ffffff; padding: 0px; }");
		this.targetButton.hide();
		this.targetButton.clicked.connect(this, "targetButtonClicked()");
		
		int frameWidth = this.style().pixelMetric(PixelMetric.PM_DefaultFrameWidth);
		this.setStyleSheet("QLineEdit { padding-right: " + (clearButton.sizeHint().width() + frameWidth + 1) + "px; } ");
		this.textChanged.connect(this, "updateClearButton(String)");
		
		// 検索対象切り替えメニュー
		targetMenu = new QMenu(this);
		QActionGroup targetGroup = new QActionGroup(this);
		targetGroup.setExclusive(true);
		allNotesAction = addContextAction(tr("Search All Notes"));
		targetGroup.addAction(allNotesAction);
		targetMenu.addAction(allNotesAction);
		currentContextAction = addContextAction(tr("Search Current Context"));
		targetGroup.addAction(currentContextAction);
		targetMenu.addAction(currentContextAction);
		targetGroup.triggered.connect(this, "toggleSearchTarget(QAction)");
		
		// 検索対象を初期状態をiniファイルから取得して設定
		final SearchTarget target = Global.searchTarget();
		if (target == SearchTarget.AllNotes) {
			allNotesAction.setChecked(true);
			toggleSearchTarget(allNotesAction);
		} else if (target == SearchTarget.CurrentContext) {
			currentContextAction.setChecked(true);
			toggleSearchTarget(currentContextAction);
		}
	}
	
	private void toggleSearchTarget(QAction action) {
		if (action == allNotesAction) {
			defaultText = new String(tr("Search All Notes"));
			Global.setSearchTarget(SearchTarget.AllNotes);
		} else if (action == currentContextAction) {
			defaultText = new String(tr("Search Current Context"));
			Global.setSearchTarget(SearchTarget.CurrentContext);
		}
    	setDefaultText();
    	this.clearFocus();
	}
	
	public SearchTarget currentSearchTarget() {
		if (allNotesAction.isChecked()) {
			return SearchTarget.AllNotes;
		} else if (currentContextAction.isChecked()) {
			return SearchTarget.CurrentContext;
		}
		
		return SearchTarget.AllNotes;	// デフォルト
	}
	
	@Override
	protected void resizeEvent(QResizeEvent event) {
		int frameWidth = style().pixelMetric(PixelMetric.PM_DefaultFrameWidth);
		
		QSize clearSize = clearButton.sizeHint();
		clearButton.move(rect().right() - frameWidth - clearSize.width(), (rect().bottom() + 1 - clearSize.height()) / 2);
		
		setTextMargins(targetButton.sizeHint().width(), 0, clearSize.width() + frameWidth, 0);
		targetButton.setFixedHeight(rect().bottom() + 1);
		targetButton.move(0,0);
		targetButton.setVisible(true);
	}
	
	@SuppressWarnings("unused")
	private void updateClearButton(String text) {
		clearButton.setVisible(!text.isEmpty());
	}
	
	public void setDefaultText() {
		if (text().trim().equals("")) {
			blockSignals(true);
			setText(defaultText);
			setStyleSheet(inactiveColor);
			blockSignals(false);
		}
	}
	
	@Override
	protected void focusInEvent(QFocusEvent event) {
		super.focusInEvent(event);
		if (text().equals(defaultText)) {
			blockSignals(true);
			setText("");
			blockSignals(false);
		}
		this.setStyleSheet(activeColor);
	}
	
	@Override
	protected void focusOutEvent(QFocusEvent event) {
		super.focusOutEvent(event);
		if (text().trim().equals("")) {
			blockSignals(true);
			setText(defaultText);
			blockSignals(false);
			setStyleSheet(inactiveColor);
		}
	}
	
	@SuppressWarnings("unused")
	private void targetButtonClicked() {
		QPoint globalPos = this.mapToGlobal(new QPoint(0, 0));
		targetMenu.popup(new QPoint(globalPos.x(), globalPos.y() + rect().bottom() + 1));
	}
	
    private QAction addContextAction(String name) {
    	QAction newAction = new QAction(this);
		newAction.setText(name);
		newAction.setCheckable(true);
		return newAction;
    }
    
    public String getSearchQuery() {
    	if (currentSearchTarget() == SearchTarget.AllNotes) {
    		return this.text();
    	} else if (currentSearchTarget() == SearchTarget.CurrentContext) {
    		return appendSearchQuery();
    	}
    	
    	return this.text();
    }
    
	private String appendSearchQuery() {
		StringBuilder query = new StringBuilder();
		
    	String stack = getTargetStack();
    	if (!stack.trim().equals("")) {
    		query.append("stack:" + stack.trim() + " ");
    	}
    	String notebook = getTargetNotebook();
    	if (!notebook.trim().equals("")) {
    		String notebookName = conn.getNotebookTable().getNotebook(notebook).getName();
    		query.append("notebook:" + notebookName + " ");
    	}
    	for (String tag: getTargetTags()) {
    		if (!tag.trim().equals("")) {
    			String tagName = conn.getTagTable().getTag(tag).getName();
    			query.append("tag:" + tagName + " ");
    		}
    	}
    	query.append(this.text());
    	
    	return new String(query);
    }

	public String getTargetStack() {
		return targetStackName;
	}
	
	public void setTargetStack(String targetStack) {
		this.targetStackName = new String(targetStack);
	}

	public String getTargetNotebook() {
		return targetNotebookGuid;
	}
	
	public void setTargetNotebook(String targetNotebook) {
		this.targetNotebookGuid = new String(targetNotebook);
	}

	public List<String> getTargetTags() {
		return targetTagGuids;
	}
	
	public void addTargetTag(String targetTag) {
		this.targetTagGuids.add(targetTag);
	}
}
