//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
// 
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Text;

namespace WeakReferenceDocuments
{
	class Document
	{
		private FileInfo fi;
		private WeakReference content;
		private string ReadFile()
		{
			FileStream fs = null;
			byte [] buffer = null;
			string c = null;
			try
			{
				fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
				buffer = new byte[fs.Length + 1];
				int bytesread = fs.Read(buffer, 0, (int)fs.Length);
				buffer[bytesread] = (byte)'\0';
				c = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
				content = new WeakReference(c);
			}
			finally
			{
				buffer = null;
				if(fs != null)
					fs.Close();
			}
			return c;
		}
		public Document()
		{
		}
		public Document(FileInfo fi)
		{
			this.fi = fi;
			content = new WeakReference(null);
		}
		public string Display
		{
			get
			{
				StringBuilder sb = new StringBuilder();
				sb.Append(fi.Name);
				sb.Append(" ");
				sb.Append(Convert.ToString(fi.Length));
//				sb.Append(" ");
//				string s = (string)content.Target;
//				if(s == null)
//					sb.Append("Not in memory");
//				else
//					sb.Append("In memory");
//				s = null;
				return sb.ToString();
			}
		}
		public bool ContentValid
		{
			get
			{
				string c = (string)content.Target;
				if(c == null)
					return false;
				else
				{
					c = null;
					return true;
				}
			}
		}
		public string Content
		{
			get
			{
				string c = (string)content.Target;
				if(c == null)
				{
					Trace.WriteLine("Target collected.");
					c = ReadFile();
				}
				else
				{
					Trace.WriteLine("Target in memory.");
				}
				return c;
			}
		}
	}

	/// <summary>
	/// Podsumowanie WeakReferenceForm.
	/// </summary>
	public class WeakReferenceForm : System.Windows.Forms.Form
	{
		private DirectoryInfo directoryInfo;
		private Document [] files;
		private System.Windows.Forms.ComboBox documentList;
		private System.Windows.Forms.RichTextBox text;
		private System.Windows.Forms.StatusBar statusBar;
		/// <summary>
		/// Wymagana zmienna.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public WeakReferenceForm()
		{
			//
			// Wymagane do obsługi Windows Form Designer
			//
			InitializeComponent();

			try
			{
				Cursor.Current = Cursors.WaitCursor;
				directoryInfo = new DirectoryInfo(@"..\..\docs");
				FileInfo [] fi = directoryInfo.GetFiles(@"*.txt");
				files = new Document[fi.Length];
				for(int i = 0;i < files.Length;i++)
				{
					files[i] = new Document(fi[i]);
				}
				documentList.DataSource = files;
				documentList.DisplayMember = "Display";
				Document doc = (Document)documentList.SelectedItem;
				Cursor.Current = Cursors.Default;
			}
			catch(DirectoryNotFoundException)
			{
                MessageBox.Show("Nie można odnaleźć katalogu z dokumentami.", "Błąd katalogu",
                                MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
			}
		}

		/// <summary>
		/// Oczyszczenie używanych zasobów.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Metoda wymagana do obsługi Designera - nie należy modyfikować
		/// zawartości tej metody przy użyciu edytora kodu.
		/// </summary>
		private void InitializeComponent()
		{
			this.documentList = new System.Windows.Forms.ComboBox();
			this.text = new System.Windows.Forms.RichTextBox();
			this.statusBar = new System.Windows.Forms.StatusBar();
			this.SuspendLayout();
			// 
			// documentList
			// 
			this.documentList.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.documentList.Location = new System.Drawing.Point(8, 16);
			this.documentList.Name = "documentList";
			this.documentList.Size = new System.Drawing.Size(544, 31);
			this.documentList.TabIndex = 0;
			this.documentList.SelectedIndexChanged += new System.EventHandler(this.OnFileChange);
			// 
			// text
			// 
			this.text.Location = new System.Drawing.Point(8, 56);
			this.text.Name = "text";
			this.text.ReadOnly = true;
			this.text.Size = new System.Drawing.Size(536, 424);
			this.text.TabIndex = 1;
			this.text.Text = "";
			// 
			// statusBar
			// 
			this.statusBar.Location = new System.Drawing.Point(0, 496);
			this.statusBar.Name = "statusBar";
			this.statusBar.Size = new System.Drawing.Size(560, 22);
			this.statusBar.TabIndex = 2;
			// 
			// WeakReferenceForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
			this.ClientSize = new System.Drawing.Size(560, 518);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.statusBar,
																		  this.text,
																		  this.documentList});
			this.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.Name = "WeakReferenceForm";
			this.Text = "Formularz WeakReference";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// Główny punkt wejścia dla aplikacji.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new WeakReferenceForm());
		}

		private void OnFileChange(object sender, System.EventArgs e)
		{
			Cursor.Current = Cursors.WaitCursor;
			ComboBox c = sender as ComboBox;
			if(c == null)
				return;
			Document doc = (Document)c.SelectedItem;
//			if(doc.ContentValid)
//				statusBar.Text = "Zawartość w pamięci";
//			else
//				statusBar.Text = "Zawartość usunięta";
			string s = doc.Content;
			text.Text = string.Copy(s);
			s = null;
			Cursor.Current = Cursors.Default;
		}
	}
}
