using System;
using System.IO;
using System.Data;
using NUnit.Framework;
using MySql.Data.MySqlClient;
using MySql.Data.Types;

namespace Orciid.Core
{
	/// <summary>
	/// Tests to check for following bugs:
	/// - Collection title does not appear when viewing slideshows that contain images that
	///   current user does not have access to
	/// - Personal images that are not shared are not available to other users who also have
	///   access to personal images, even if they are in a slideshow context
	/// </summary>
	[TestFixture]
	public class TestPersonalImagePermissions
	{
		private const string DB_TYPE = "MYSQL";
		private const string DB_SERVER = "localhost";
		private const string DB_USER = "mdid2test";
		private const string DB_PASSWORD = "mdid2test";
		private const string DB_DATABASE = "mdid2test";

		private const string CONFIG_FILE = @"<config>
	<content>
		<resourcepath>{0}</resourcepath>
	</content>
	<database>
		<servertype>{5}</servertype>
		<connection>server={1};User ID={2};Password={3};database={4};charset=utf8;</connection>
		<upgradeable>true</upgradeable>
	</database>
	<smtp>
		<server>localhost</server>
		<sender></sender>
	</smtp>
</config>";

		private string tempTestDir;

		/// <summary>
		/// Set up tests
		/// </summary>
		[SetUp]
		public void Setup()
		{
			tempTestDir = Path.Combine(Path.GetTempPath(), this.GetType().Name);
			Directory.CreateDirectory(tempTestDir);
			Console.WriteLine("Creating config file at " + tempTestDir);
			using (StreamWriter writer = File.CreateText(Path.Combine(tempTestDir, "config.xml")))
				writer.WriteLine(CONFIG_FILE, 
					tempTestDir,
					DB_SERVER, 
					DB_USER, 
					DB_PASSWORD, 
					DB_DATABASE, 
					DB_TYPE);
			Configuration.Instance.Initialize(tempTestDir);
		}

		/// <summary>
		/// Clean up after tests
		/// </summary>
		[TearDown]
		public void Cleanup()
		{
			// currently only works with MySQL
			Assert.AreEqual("MYSQL", DB_TYPE);
			Console.WriteLine("Removing database tables");
			using (MySqlConnection conn = 
					   new MySqlConnection(Configuration.Instance.GetString("database.connection")))
			{
				conn.Open();
				DataSet s = new DataSet();
				new MySqlDataAdapter("SHOW TABLES", conn).Fill(s);
				foreach (DataRow row in s.Tables[0].Rows)
				{
					string table = row[0].ToString();
					Console.WriteLine("  " + table);
					new MySqlCommand(String.Format("DROP TABLE {0}", table), conn).ExecuteNonQuery();
				}
				conn.Close();
			}
			Console.WriteLine("Removing temporary directory");
			Directory.Delete(tempTestDir, true);
		}

		private void PopulateTestData()
		{
			User.GetByLogin("admin", "admin").Activate(null);
			
			User fac1 = new User();
			fac1.Login = "fac1";
			fac1.FirstName = "Faculty";
			fac1.LastName = "One";
			fac1.Email = "example@example.com";
			fac1.Update();
			fac1.SetPassword("fac1");

			User fac2 = new User();
			fac2.Login = "fac2";
			fac2.FirstName = "Faculty";
			fac2.LastName = "Two";
			fac2.Email = "example@example.com";
			fac2.Update();
			fac2.SetPassword("fac2");

			User stu1 = new User();
			stu1.Login = "stu1";
			stu1.FirstName = "Student";
			stu1.LastName = "One";
			stu1.Email = "example@example.com";
			stu1.Update();
			stu1.SetPassword("stu1");

			MemberUserGroup faculty = UserGroup.GetByTitlePattern("Faculty")[0] as MemberUserGroup;
			Assert.IsNotNull(faculty);
			faculty.Add(fac1);
			faculty.Add(fac2);
		}

		private Collection GetPersonalCollection()
		{
			foreach (Collection coll in Collection.GetCollections())
				if (coll.Title == "Personal Images")
					return coll;
			Assert.Fail();
			return null;
		}

		/// <summary>
		/// Check for collection title bug
		/// </summary>
		[Test, Category("RequiresDB")]
		public void CheckCollectionTitle()
		{
			PopulateTestData();

			User.GetByLogin("fac1", "fac1").Activate(null);
			Collection personal = GetPersonalCollection();

			// create a personal image
			Image image = personal.CreateImage(true);
			image["Title"].Add("Test Image");
			image.Update();

			// put image in a new slideshow
			Slideshow slideshow = new Slideshow();
			slideshow.Title = "Test Slideshow";
			Slide slide = new Slide();
			slide.ImageID = image.ID;
			slideshow.Add(slide);
			slideshow.ArchiveFlag = false;
			slideshow.Update();
			slideshow.GetAccessControl().AddUserPrivilege(Privilege.ViewSlideshow, Privilege.None,
				User.GetByLogin("stu1").ID);

			// check slideshow as student
			User.GetByLogin("stu1", "stu1").Activate(null);
			Slideshow viewshow = Slideshow.GetByID(slideshow.ID);
			Assert.IsNotNull(viewshow);
			Slide[] slides = viewshow.GetSlides();
			Image[] images = viewshow.GetImages();
			Assert.IsNotNull(images);
			Assert.IsNotNull(images[0]);
			Assert.AreEqual("Personal Images", images[0].GetCollectionTitle());
		}
	}
}
