context: #region License
  
  // Copyright (c) 2013, ClearCanvas Inc.
  // All rights reserved.
  // http://www.ClearCanvas.ca
  //
  // This file is part of the ClearCanvas RIS/PACS open source project.
  //
  // The ClearCanvas RIS/PACS open source project is free software: you can
  // redistribute it and/or modify it under the terms of the GNU General Public
  // License as published by the Free Software Foundation, either version 3 of the
  // License, or (at your option) any later version.
  //
  // The ClearCanvas RIS/PACS open source project is distributed in the hope that it
  // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
  // Public License for more details.
  //
  // You should have received a copy of the GNU General Public License along with
  // the ClearCanvas RIS/PACS open source project.  If not, see
  // <http://www.gnu.org/licenses/>.
  
  #endregion
  
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using Macro.Dicom;
  using Macro.Desktop;
  using Macro.Desktop.Actions;
  using Macro.Desktop.Tools;
  using Macro.Desktop.Tables;
  using Macro.Common;
  using Macro.Common.Utilities;
  using Macro.Dicom.Utilities.Anonymization;
  using Macro.ImageViewer.Common.Auditing;
  
  namespace Macro.Utilities.DicomEditor
  {
      [ExtensionPoint()]
  	public sealed class DicomEditorToolExtensionPoint : ExtensionPoint<ITool>
      {
      }
  
  	public sealed class DicomEditorComponentViewExtensionPoint : ExtensionPoint<IApplicationComponentView>
      {
      }
  
      public interface IDicomEditorDumpManagement
      {
          int LoadedFileDumpIndex { get; set; }
  
          void RevertEdits(bool revertAll);
  
      	void Anonymize(bool applyToAll);
  
  		int LoadedFileCount { get; }
  		void SaveAll();
  
          bool TagExists(uint tag);
  
          void EditTag(uint tag, string value, bool applyToAll);
  
          void DeleteTag(uint tag, bool applyToAll);
      }
  
  	public interface IDicomEditorToolContext : IToolContext
  	{
          IDicomEditorDumpManagement DumpManagement { get; }
  
          DicomEditorTag SelectedTag { get; }
  
          IList<DicomEditorTag> SelectedTags { get; }
  
  		event EventHandler SelectedTagChanged;
  
          event EventHandler<DisplayedDumpChangedEventArgs> DisplayedDumpChanged;
  
  		//Edited.
          event EventHandler TagEdited;
  
  		ClickHandlerDelegate DefaultActionHandler { get; set; }
  
  		IDesktopWindow DesktopWindow { get; }
  
  		void UpdateDisplay();
  
  		bool IsLocalFile { get; }
  
  		event EventHandler IsLocalFileChanged;
  	}
  
      [AssociateView(typeof(DicomEditorComponentViewExtensionPoint))]
      public class DicomEditorComponent : ApplicationComponent, IDicomEditorDumpManagement
      {
          public class DicomEditorToolContext : ToolContext, IDicomEditorToolContext
          {
              DicomEditorComponent _component;
  
              public DicomEditorToolContext(DicomEditorComponent component)
              {
                  Platform.CheckForNullReference(component, "component");
                  _component = component;
              }
  
              #region IDicomEditorToolContext Members
  
              public IDicomEditorDumpManagement DumpManagement
              {
                  get { return _component; }
              }
  
              public DicomEditorTag SelectedTag
              {
                  get
                  {
                      if (_component._currentSelection == null)
                          return null;
  
                      return _component._currentSelection.Item as DicomEditorTag;
                  }
              }
  
              public IList<DicomEditorTag> SelectedTags
              {
                  get
                  {
                      if (_component._currentSelection == null)
                          return null;
  
                      List<DicomEditorTag> selectedTags = new List<DicomEditorTag>();
  
                      foreach (DicomEditorTag tag in _component._currentSelection.Items)
                          selectedTags.Add(tag);
  
                      return selectedTags;
                  }
              }
  
              public event EventHandler SelectedTagChanged
              {
                  add { _component._selectedTagChangedEvent += value; }
                  remove { _component._selectedTagChangedEvent -= value; }
              }
  
              public event EventHandler<DisplayedDumpChangedEventArgs> DisplayedDumpChanged
              {
                  add { _component._displayedDumpChangedEvent += value; }
                  remove { _component._displayedDumpChangedEvent -= value; }
              }
  
              public event EventHandler TagEdited
              {
                  add { _component._tagEditedEvent += value; }
                  remove { _component._tagEditedEvent -= value; }
              }
  
              public ClickHandlerDelegate DefaultActionHandler
              {
                  get { return _component._defaultActionHandler; }
                  set { _component._defaultActionHandler = value; }
              }
  
              public IDesktopWindow DesktopWindow
              {
                  get { return _component.Host.DesktopWindow; }
              }
  
              public void UpdateDisplay()
              {
                  _component.UpdateComponent();
  			}
  
  			/// <summary>
  			/// Gets a value indicating the the current loaded file is stored on the local file system (even if only temporarily).
  			/// </summary>
  			/// <remarks>
  			/// This value serves to distinguish files that exist on the local file system versus those that may not, such as those from a streaming source.
  			/// </remarks>
          	public bool IsLocalFile
          	{
  				get { return _component.IsLocalFile; }
          	}
  
  			public event EventHandler IsLocalFileChanged
  			{
  				add { _component._isLocalFileChanged += value; }
  				remove { _component._isLocalFileChanged -= value; }
  			}
  
              #endregion
          }
  
          #region IDicomEditorDumpManagement Members
  
          public int LoadedFileDumpIndex
          {
              get { return _position; }
              set 
              {
                  Platform.CheckPositive(_loadedFiles.Count, "_loadedDicomDumps.Length");
  
                  if (value < 0)
                      _position = 0;
                  else if (value > _loadedFiles.Count - 1)
                      _position = _loadedFiles.Count - 1;
                  else
                      _position = value;
              }
          }
  
          public void RevertEdits(bool revertAll)
          {
              if (revertAll == true)
              {
                  for (int i = 0; i < _loadedFiles.Count; i++)
                  {
                      _loadedFiles[i] = new DicomFile(_loadedFiles[i].Filename);
                      _loadedFiles[i].Load(DicomReadOptions.Default);
                      _dirtyFlags[i] = false;
                  }
              }
              else
              {
                  _loadedFiles[_position] = new DicomFile(_loadedFiles[_position].Filename);
                  _loadedFiles[_position].Load(DicomReadOptions.Default);
                  _dirtyFlags[_position] = false;
              }
          }
  
          public void Anonymize(bool applyToAll)
          {
              if (applyToAll == false)
              {
              	if (!WarnReportOrAttachmentAnonymization(_loadedFiles[_position]))
              		return;
  
  				_anonymizer.Anonymize(_loadedFiles[_position]);
  				_dirtyFlags[_position] = true;
              }
              else
              {
              	if (!WarnReportOrAttachmentAnonymization())
              		return;
  
                  for (int i = 0; i < _loadedFiles.Count; i++)
                  {
  					_anonymizer.Anonymize(_loadedFiles[i]);
  					_dirtyFlags[i] = true;
                  }
              }
          }
  
      	public int LoadedFileCount
      	{
      		get { return _loadedFiles.Count; }
      	}
  
  		public void SaveAll()
  		{
              if (!WarnSaveEditedReportsOrAttachments())
                  return;
  
  			var modifiedInstances = new AuditedInstances();
  			var failureCount = 0;
  
  			for (int i = 0; i < _loadedFiles.Count; i++)
  			{
  				var file = _loadedFiles[i];
  				try
  				{
  					var studyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].ToString();
  					var patientId = file.DataSet[DicomTags.PatientId].ToString();
  					var patientsName = file.DataSet[DicomTags.PatientsName].ToString();
  
  					file.Save(DicomWriteOptions.Default);
  					_dirtyFlags[i] = false;
  
  					modifiedInstances.AddInstance(patientId, patientsName, studyInstanceUid);
  				}
  				catch (Exception ex)
  				{
  					++failureCount;
  
  					if (file != null && !string.IsNullOrEmpty(file.Filename))
  						Platform.Log(LogLevel.Warn, ex, "An exception was encountered while trying to update the file \'{0}\'.", file.Filename);
  					else
  						Platform.Log(LogLevel.Warn, ex, "An unexpected error was encountered while trying to update a file.");
  				}
  			}
  
  			if (failureCount > 0)
  				Host.DesktopWindow.ShowMessageBox(SR.MessageErrorUpdatingSomeFiles, MessageBoxActions.Ok);
  
  			AuditHelper.LogUpdateInstances(new string[0], modifiedInstances, EventSource.CurrentUser, EventResult.Success);
  		}
  
          public bool TagExists(uint tag)
          {
              if (this.IsMetainfoTag(tag))
              {
                  return _loadedFiles[_position].MetaInfo.Contains(tag);
              }
              else
              {
                  return _loadedFiles[_position].DataSet.Contains(tag);
              }
          }
  
          public void EditTag(uint tag, string value, bool applyToAll)
          {
                  if (applyToAll == false)
                  {
                      if (this.IsMetainfoTag(tag))
                      {
                          _loadedFiles[_position].MetaInfo[tag].SetStringValue(value);
                      }
                      else
                      {
                          _loadedFiles[_position].DataSet[tag].SetStringValue(value);
                      }
                      _dirtyFlags[_position] = true;
                      EventsHelper.Fire(_tagEditedEvent, this, EventArgs.Empty);
                  }
                  else
                  {
                      for (int i = 0; i < _loadedFiles.Count; i++)
                      {
                          if (this.IsMetainfoTag(tag))
                          {
                              _loadedFiles[i].MetaInfo[tag].SetStringValue(value);
                          }
                          else
                          {
                              _loadedFiles[i].DataSet[tag].SetStringValue(value);
                          }
                          _dirtyFlags[i] = true;
                          EventsHelper.Fire(_tagEditedEvent, this, EventArgs.Empty);
                      }
                  }
          }
  
          public void DeleteTag(uint tag, bool applyToAll)
          {
              if (applyToAll == false)
              {
                  if (this.IsMetainfoTag(tag))
                  {
                      _loadedFiles[_position].MetaInfo[tag] = null;
                  }
                  else
                  {
                      _loadedFiles[_position].DataSet[tag] = null;
                  }
                  _dirtyFlags[_position] = true;
              }
              else
              {
                  for (int i = 0; i < _loadedFiles.Count; i++)
                  {
                      if (this.IsMetainfoTag(tag))
                      {
                          _loadedFiles[i].MetaInfo[tag] = null;
                      }
                      else
                      {
                          _loadedFiles[i].DataSet[tag] = null;
                      }
                      _dirtyFlags[i] = true;
                  }
              }
          }    
  
          #endregion
  
          public DicomEditorComponent()
          {
              _dicomTagData = new Table<DicomEditorTag>();
              _dicomTagData.Columns.Add(new TableColumn<DicomEditorTag, string>(SR.ColumnHeadingGroupElement, delegate(DicomEditorTag d) { return d.DisplayKey; }, null, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return DicomEditorTag.TagCompare(one, two, SortType.GroupElement); }));
              _dicomTagData.Columns.Add(new TableColumn<DicomEditorTag, string>(SR.ColumnHeadingTagName, delegate(DicomEditorTag d) { return d.TagName; }, null, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return DicomEditorTag.TagCompare(one, two, SortType.TagName); }));
              _dicomTagData.Columns.Add(new TableColumn<DicomEditorTag, string>(SR.ColumnHeadingVR, delegate(DicomEditorTag d) { return d.Vr; }, null, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return DicomEditorTag.TagCompare(one, two, SortType.Vr); }));
              _dicomTagData.Columns.Add(new TableColumn<DicomEditorTag, string>(SR.ColumnHeadingLength, delegate(DicomEditorTag d) { return d.Length; }, null, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return DicomEditorTag.TagCompare(one, two, SortType.Length); }));
              _dicomTagData.Columns.Add(new TableColumn<DicomEditorTag, string>(SR.ColumnHeadingValue, delegate(DicomEditorTag d) { return d.Value; }, delegate(DicomEditorTag d, string value)
                                                                                                                                                      {
                                                                                                                                                          if (d.IsEditable())
                                                                                                                                                          {
                                                                                                                                                              d.Value = value;
                                                                                                                                                              _dirtyFlags[_position] = true;
                                                                                                                                                              EventsHelper.Fire(_tagEditedEvent, this, EventArgs.Empty);
                                                                                                                                                          }
                                                                                                                                                      }, 1.0f, delegate(DicomEditorTag one, DicomEditorTag two) { return DicomEditorTag.TagCompare(one, two, SortType.Value); }));
              _title = "";
              _loadedFiles = new List<DicomFile>();
              _position = 0;
              _dirtyFlags = new List<bool>();
  
  			_anonymizer = new DicomAnonymizer();
          	_anonymizer.ValidationOptions = ValidationOptions.RelaxAllChecks;
          }
  
          public ActionModelRoot ToolbarModel
          {
              get { return _toolbarModel; }
          }
  
  		public ActionModelNode ContextMenuModel
          {
  
gt:             get { return _contextMenuModel; }