//-----------------------------------------------------------------------
//  This file is part of the Microsoft Code Samples.
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved.
// 
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation.  See these other
//materials for detailed information regarding Microsoft code samples.
// 
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.SqlServer.Management.Smo;
using nmo = Microsoft.SqlServer.Management.Nmo;
using Microsoft.SqlServer.Management.Nmo;

namespace RulesControls
{
    // An abstract control allowing the selection of an SMO object retrieved through enumeration.
    // Type P is the parent SMO class, e.g., "Server", and type T is the type selected by the
    // implementing class, e.g., "Database". When the "ParentContext" is set, the "ComboBox" is
    // populated.
    public abstract class SmoComboBox<T, P> : ComboBox
        where T : SqlSmoObject
        where P : SqlSmoObject
    {
        // Default constructor.
        public SmoComboBox()
            : base()
        {
            this.SelectedValueChanged += new EventHandler(OnSelectedChanged);
        }

        // Gets the currently selected SMO object.
        public T Selected
        {
            get { return this.SelectedItem as T; }
        }

        // Gets or sets the parent context.
        public P ParentContext
        {
            get { return this.parent; }
            set
            {
                this.parent = value;
                this.Items.Clear();
                this.ResetText();

				if (null != this.ParentContext)
				{
					this.PopulateItems();
				}

				if (this.Items.Count == 1)
				{
					this.SelectedIndex = 0;
				}

				this.OnSelectedChanged(this, new EventArgs());
            }
        }

        // Event raised when an SMO object is selected using this control.
        public event EventHandler<SmoEventArgs<T>> SelectedChanged;

        // Parent context change event handler delegate.
        public void HandleParentContextChange(object sender, SmoEventArgs<P> e)
        {
            this.ParentContext = e.ParentContext;
        }

        // Method called when the "ParentContext" has changed.
        protected abstract void PopulateItems();

        private void OnSelectedChanged(object sender, EventArgs e)
        {
            if (null != this.SelectedChanged)
            {
                this.SelectedChanged(this, new SmoEventArgs<T>(this.Selected));
            }
        }

        private P parent;
    }

    // Event indicating an SMO object has been chosen using a control.
    public class SmoEventArgs<T> : EventArgs
        where T : SqlSmoObject
    {
        public SmoEventArgs(T parent) 
            : base()
        {
            this.parent = parent;
        }

        public T ParentContext
        {
            get { return this.parent; }
        }

        private T parent;
    }

    // "ComboBox" selecting a "Column" given a "TableViewBase" parent context.
    public class ColumnChooser : SmoComboBox<Column, TableViewBase>
    {
        override protected void PopulateItems()
        {
            foreach (Column column in this.ParentContext.Columns)
            {
                this.Items.Add(column);
            }
        }
    }

    // "ComboBox" selecting a "TableViewBase" given a "Database" parent context.
    public class TableViewBaseChooser : SmoComboBox<TableViewBase, Database>
    {
        protected override void PopulateItems()
        {
            foreach (Table table in this.ParentContext.Tables)
            {
                this.Items.Add(table);
            }
            foreach (Microsoft.SqlServer.Management.Smo.View view in this.ParentContext.Views)
            {
                this.Items.Add(view);
            }
        }
    }

    // "ComboBox" selecting a "Database" given a "Server" parent context.
    public class DatabaseChooser : SmoComboBox<Database, Server>
    {
        protected override void PopulateItems()
        {
            foreach (Database db in this.ParentContext.Databases)
            {
                this.Items.Add(db);
            }
        }
    }

	public class InstanceChooser : SmoComboBox<Instance, Server>
	{
		protected override void PopulateItems()
		{
			foreach (Instance instance in this.ParentContext.NotificationServices.Instances)
			{
				this.Items.Add(instance);
			}
		}
	}

	public class ApplicationChooser : SmoComboBox<nmo.Application, Instance>
	{
		protected override void PopulateItems()
		{
			foreach (nmo.Application application in this.ParentContext.Applications)
			{
				this.Items.Add(application);
			}
		}
	}

	public class SubscriptionClassChooser : SmoComboBox<SubscriptionClass, nmo.Application>
	{
		protected override void PopulateItems()
		{
			foreach (SubscriptionClass sc in this.ParentContext.SubscriptionClasses)
			{
				this.Items.Add(sc);
			}
		}
	}

	public class ConditionEventRuleChooser : SmoComboBox<SubscriptionConditionEventRule, SubscriptionClass>
	{
		protected override void PopulateItems()
		{
			foreach (SubscriptionConditionEventRule rule in this.ParentContext.SubscriptionConditionEventRules)
			{
				this.Items.Add(rule);
			}
		}
	}
}
