/*
 *  TLV - Trace Log Visualizer
 *
 *  Copyright (C) 2008-2011 by Nagoya Univ., JAPAN
 *
 *  上記著作権者は，以下の(1)〜(4)の条件を満たす場合に限り，本ソフトウェ
 *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
 *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *      と．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *        報告すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
 *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
 *      免責すること．
 *
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
 *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
 *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
 *  の責任を負わない．
 *
 *  @(#) $Id: ConditionSettingPanel.cs 89 2011-04-08 11:02:14Z nagasima $
 */﻿
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using NU.OJL.MPRTOS.TLV.Core.Controls;
using NU.OJL.MPRTOS.TLV.Core.Search.ConditionPanels;
using NU.OJL.MPRTOS.TLV.Core.Search.SearchConditions;
using NU.OJL.MPRTOS.TLV.Core.Search.Filters;
using NU.OJL.MPRTOS.TLV.Core.FileContext.VisualizeData;


namespace NU.OJL.MPRTOS.TLV.Core.Search
{
	//詳細検索画面に張り付ける検索条件のパネル
	class ConditionSettingPanel : Panel
	{
		private TraceLogVisualizerData _data = null;
		private BaseConditionPanel _baseConditionPanel = null;
		public BaseConditionPanel baseConditionPanel { set { _baseConditionPanel = value; } get { return _baseConditionPanel; } }
		private Button _searchBackwardButton = null;
		public Button SearchBackwardButton { set { _searchBackwardButton = value; } get { return _searchBackwardButton; } }
		private Button _searchForwardButton = null;
		public Button SearchForwardButton { set { _searchForwardButton = value; } get { return _searchForwardButton; } }
		private Button _searchWholeButton = null;
		public Button SearchWholeButton { set { _searchWholeButton = value; } get { return _searchWholeButton; } }

		private Button _addRefiningConditionButton = null;
		private RadioButton _andRadioButton = null;
		private RadioButton _orRadioButton = null;

		private List<ConditionPanel> _refiningConditionPanels = null;
		private int _panelID = 0;
		public int panelID { set { _panelID = value; } get { return _panelID; } }
		private string _timeScale; //タイムラインの時間単位（s, ms, μsなど）
		private int _nextComponentLocationY = 0;
		private int _refiningConditionPanelMargin = 20; //絞込み条件パネルを主条件パネルに対してどれだけインデントするか
		private int _maxPanelWidth = 585;
		private int _maxPanelHeight = 300;
		private Boolean _isAlreadyMaximumSizeChanged = false;

		private List<VisualizeLog> _eventLogs;

		public ConditionSettingPanel(TraceLogVisualizerData data, List<VisualizeLog> eventLogs, int panelID)
		{
			_data = data;
			_eventLogs = eventLogs;
			_timeScale = _data.ResourceData.TimeScale;
			_panelID = panelID;
			_refiningConditionPanels = new List<ConditionPanel>();
			initializeCompoent();
		}

		private void initializeCompoent()
		{
			this.Width = _maxPanelWidth;
			this.Height = _maxPanelHeight;
			this.MaximumSize = new System.Drawing.Size(_maxPanelWidth, _maxPanelHeight);
			this.AutoScroll = true;
			this.HScroll = true;
			this.BorderStyle = BorderStyle.FixedSingle;
			setBaseConditionPanel();
			setSearchButton();
			setAddRefiningConditionButton();
			setANDORRadioButton();
		}

		private void setBaseConditionPanel()
		{
			_baseConditionPanel = new BaseConditionPanel(_data, _eventLogs, _panelID, this.Size);
			_baseConditionPanel.Location = new System.Drawing.Point(0, 0); //基本条件パネルは条件設定パネルの一番上へ配置
			_baseConditionPanel.SizeChanged += delegate(object o, EventArgs e)
			{
				if (this.Width < _baseConditionPanel.Width)
				{
					this.Width = _baseConditionPanel.Width;
				}
			};
			this.Controls.Add(_baseConditionPanel);
			_nextComponentLocationY = _baseConditionPanel.Height + 2;
		}

		private void setSearchButton()
		{
			_searchBackwardButton = new Button();
			_searchBackwardButton.Name = "searchBackwardButton:" + _panelID;
			_searchBackwardButton.Text = "後ろを検索";
			_searchBackwardButton.Width = 80;
			_searchBackwardButton.Location = new System.Drawing.Point(//
			   _baseConditionPanel.deleteButton.Location.X + _baseConditionPanel.deleteButton.Width + 40, //
															 _baseConditionPanel.deleteButton.Location.Y);
			_searchForwardButton = new Button();
			_searchForwardButton.Name = "searchForwardButton:" + _panelID;
			_searchForwardButton.Text = "次を検索";
			_searchForwardButton.Width = 80;
			_searchForwardButton.Location = new System.Drawing.Point(//
									 _searchBackwardButton.Location.X + _searchBackwardButton.Width + 5, _searchBackwardButton.Location.Y);
			_searchWholeButton = new Button();
			_searchWholeButton.Name = "searchForwardButton:" + _panelID;
			_searchWholeButton.Text = "全体検索";
			_searchWholeButton.Width = 80;
			_searchWholeButton.Location = new System.Drawing.Point(//
									 _searchForwardButton.Location.X + _searchForwardButton.Width + 5, _searchForwardButton.Location.Y);
			_baseConditionPanel.Controls.Add(_searchBackwardButton);
			_baseConditionPanel.Controls.Add(_searchForwardButton);
			_baseConditionPanel.Controls.Add(_searchWholeButton);
		}

		private void setAddRefiningConditionButton()
		{
			_addRefiningConditionButton = new Button();
			_addRefiningConditionButton.Name = "addRefiningConditionButton:" + _panelID;
			_addRefiningConditionButton.Text = "絞込み条件の追加";
			_addRefiningConditionButton.Location = new System.Drawing.Point(10, _nextComponentLocationY);
			_addRefiningConditionButton.Width = 120;
			_addRefiningConditionButton.Click += delegate(object o, EventArgs _e)
			{
				addRefiningConditionPanel();
			};
			this.Controls.Add(_addRefiningConditionButton);
		}

		private void addRefiningConditionPanel()
		{
			//絞込み検索条件の種類を増やす場合は、各条件に対応したパネルを生成する処理をここに追加すること。
			//（現在はタイミング条件のみであるのでハードコーディングしてある）
			ConditionPanel refiningConditionPanel = new BaseConditionWithTimingPanel(_data, _eventLogs, _panelID, _refiningConditionPanels.Count, this.Size, _refiningConditionPanelMargin, _timeScale);
			refiningConditionPanel.Location = new System.Drawing.Point(_baseConditionPanel.Location.X + _refiningConditionPanelMargin, _nextComponentLocationY);
			refiningConditionPanel.deleteButton.Click += delegate(object o, EventArgs _e)
			{
				deleteRefiningCondition(refiningConditionPanel.conditionID);
			};

			_refiningConditionPanels.Add(refiningConditionPanel);
			this.Controls.Add(refiningConditionPanel);
			_nextComponentLocationY += refiningConditionPanel.Height;

			if (_refiningConditionPanels.Count > 1)
			{
				this.Controls.Add(_andRadioButton);
				this.Controls.Add(_orRadioButton);
			}

			if (this.VerticalScroll.Visible && !_isAlreadyMaximumSizeChanged)
			{
				this.MaximumSize = new System.Drawing.Size(this.MaximumSize.Width - 15, this.MaximumSize.Height);
				_isAlreadyMaximumSizeChanged = true;
			}
		}

		private void setANDORRadioButton()
		{
			_andRadioButton = new RadioButton();
			_andRadioButton.Name = "andRadioButton:" + _panelID;
			_andRadioButton.Text = "全ての条件に一致";
			_andRadioButton.Width = 120;
			_andRadioButton.Checked = true;
			_andRadioButton.Location = new System.Drawing.Point(_addRefiningConditionButton.Location.X + _addRefiningConditionButton.Width + 20, _addRefiningConditionButton.Location.Y);

			_orRadioButton = new RadioButton();
			_orRadioButton.Name = "andRadioButton:" + _panelID;
			_orRadioButton.Text = "いずれかの条件に一致";
			_orRadioButton.Width = 140;
			_orRadioButton.Checked = false;
			_orRadioButton.Location = new System.Drawing.Point(_andRadioButton.Location.X + _andRadioButton.Width + 5, _andRadioButton.Location.Y);

			_nextComponentLocationY += _orRadioButton.Height + 5;
		}

		private void deleteRefiningCondition(int conditionID)
		{
			_refiningConditionPanels.RemoveAt(conditionID);
			updatePanel();
		}

		public void setPanelID(int panelID)
		{
			_panelID = panelID;
			_baseConditionPanel.parentPanelID = panelID;
			_baseConditionPanel.setConditionID(_panelID);
			foreach (ConditionPanel panel in _refiningConditionPanels)
			{
				panel.parentPanelID = panelID;
			}
		}

		//すべてのコンポーネントをパネル上から消去し、再配置する
		private void updatePanel()
		{
			this.AutoScrollPosition = new System.Drawing.Point(0, 0);
			this.Focus();
			this.Controls.Clear();
			_nextComponentLocationY = 0;
			int conditionID = 0;

			//基本条件と条件追加ボタンの追加
			this.Controls.Add(_baseConditionPanel);
			this.Controls.Add(_addRefiningConditionButton);
			_nextComponentLocationY = _addRefiningConditionButton.Location.Y + _addRefiningConditionButton.Height + 5;

			if (_refiningConditionPanels.Count > 1)
			{
				this.Controls.Add(_andRadioButton);
				this.Controls.Add(_orRadioButton);
			}


			//絞込み条件の追加
			foreach (ConditionPanel panel in _refiningConditionPanels)
			{
				panel.Location = new System.Drawing.Point(this.Location.X + 20, _nextComponentLocationY);
				panel.setConditionID(conditionID);
				this.Controls.Add(panel);
				_nextComponentLocationY += panel.Height + 1;
				conditionID++;
			}

			if (!this.VerticalScroll.Visible) //垂直スクロールバーが出現していない場合
			{
				this.MaximumSize = new System.Drawing.Size(_maxPanelWidth, _maxPanelHeight);
				_isAlreadyMaximumSizeChanged = false;
			}
		}

		public List<SearchFilter> getFilters()
		{
			List<SearchFilter> filters = new List<SearchFilter>();

			if (_andRadioButton.Checked) //すべてANDのときは直列フィルタを作成
			{
				SearchFilter filter = _baseConditionPanel.getSearchFilter(null);
				foreach (ConditionPanel panel in _refiningConditionPanels)
				{
					filter = panel.getSearchFilter(filter);
				}
				filters.Add(filter);
			}
			else //すべてORのときは並列フィルタを作成
			{
				foreach (ConditionPanel panel in _refiningConditionPanels)
				{
					SearchFilter filter = _baseConditionPanel.getSearchFilter(null);
					filter = panel.getSearchFilter(filter);
					filters.Add(filter);
				}
			}
			return filters;
		}

		public List<ErrorCondition> getErrorConditions()
		{
			List<ErrorCondition> errorConditions = new List<ErrorCondition>();
			ErrorCondition tmpErrorCondition = _baseConditionPanel.checkSearchCondition();
			if (tmpErrorCondition != null)
			{
				errorConditions.Add(tmpErrorCondition);
			}

			foreach (ConditionPanel panel in _refiningConditionPanels)
			{
				tmpErrorCondition = panel.checkSearchCondition();
				if (tmpErrorCondition != null)
				{
					errorConditions.Add(tmpErrorCondition);
				}
			}

			return errorConditions;
		}
	}
}
