context: using System;
  using System.IO;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using System.Text.RegularExpressions;
  using System.Globalization;
  
  using Sdl.LanguagePlatform.Core;
  using Sdl.LanguagePlatform.TranslationMemory;
  using Sdl.LanguagePlatform.TranslationMemoryApi;
  using Sdl.Community.TermInjector;
  using System.ComponentModel;
  using System.Threading;
  using System.Runtime.InteropServices;
  using System.Diagnostics;
  
  namespace Sdl.Community.TermInjector
  {
      public class TermInjectorTranslationProvider : ITranslationProvider
      {
          ///<summary>
          /// This string needs to be a unique value.
          /// This is the string that precedes the plug-in URI.
          ///</summary>    
          public static readonly string TermInjectorTranslationProviderScheme = "terminjector";
          
          //private static int instances = 0;
          //public int instancenumber;
  
          private Trie exactMatchTrieSource;
          private Trie exactMatchTrieReplaces;
          private RegexTrie<TranslationAndReplacement> regexTrieSource;
          private RegexTrie<TranslationAndReplacement> regexTrieReplaces;
          private FileBasedTranslationMemory fileTM;
  
          private TermInjectorTranslationProviderElementTermReplacementVisitor noMatchVisitor;
          private TermInjectorTranslationProviderElementTermExtractionVisitor fuzzyCurrentVisitor;
          private TermInjectorTranslationProviderElementTermExtractionVisitor fuzzyMatchVisitor;
          private TermInjectorTranslationProviderElementTermReplacementVisitor fuzzyReplaceVisitor;
  
          private RegexTrieFactory<TranslationAndReplacement> regexTrieFactory;
          private Determiniser<TranslationAndReplacement> determiniser;
          private TrieLoader trieLoader;        
  
          #region "TermInjectorTranslationOptions"
          public TermInjectorTranslationOptions Options
          {
              get;
              set;
          }
  
          private char delimiterToChar(string delimiter)
          {
              if (delimiter == "Tab")
              {
                  return '\t';
              }
              else
              {
                  return Convert.ToChar(delimiter);
              }
          }
  
          public void loadTries()
          {
              //Reset the node counter
              RegexTrie<TranslationAndReplacement>.counter = 0;
              //Load tries
              char delimiter = delimiterToChar(this.Options.Delimiter);
              //Load the exact match tries
              this.exactMatchTrieSource = new Trie();
              this.exactMatchTrieReplaces = new Trie();
              this.trieLoader.loadTrieFromFile(
                  this.Options.GlossaryFileName,
                  this.Options.MatchCase == "true" ? true : false,
                  delimiter,
                  this.exactMatchTrieSource,
                  this.exactMatchTrieReplaces);
              
              //Load regex tries
              this.regexTrieSource = new RegexTrie<TranslationAndReplacement>();
              this.regexTrieReplaces = new RegexTrie<TranslationAndReplacement>();
              //Pass the tries by ref, as determinisation needs to return a new trie
              this.trieLoader.loadRegexTrieFromFile(
                  this.Options.RegexFileName,
                  delimiter,
                  ref this.regexTrieSource,
                  ref this.regexTrieReplaces);
          }
  
          /*public void checkExistenceOfFiles()
          {
              if (this.Options.RegexFileName !="" && !File.Exists(this.Options.RegexFileName) ||
                  this.Options.TMFileName != "" && !File.Exists(this.Options.TMFileName) ||
                  this.Options.GlossaryFileName != "" && !File.Exists(this.Options.GlossaryFileName))
              {
                  MessageBox.Show("TermInjector settings refer to files that do not exist. Check that the glossary files (if defined) and the TM have correct paths.");
                  TermInjectorTranslationProviderConfDialog dialog = new TermInjectorTranslationProviderConfDialog(this.Options, this);
                  if (dialog.ShowDialog() == DialogResult.OK)
                  {
                      this.Options = dialog.Options;
                  }
                  if (dialog.ShowDialog() == DialogResult.Cancel)
                  {
                      throw new Exception();
                  }
              }
  
          }
          */
          
  
          public TermInjectorTranslationProvider(TermInjectorTranslationOptions options)
          {
              this.Options = options;
              
              //Initialize regex building objects
              this.regexTrieFactory = new RegexTrieFactory<TranslationAndReplacement>();
  
              this.determiniser = new Determiniser<TranslationAndReplacement>();
              this.trieLoader = new TrieLoader(regexTrieFactory,determiniser);
  
              //Check that the files specified in the options exist
              //this.checkExistenceOfFiles();
  
              //Load tries and TM
              try
              {
                  this.loadTries();
              }
              catch (Exception ex)
              {
                  MessageBox.Show(ex.Message);
              }
  
              this.loadTM();
              
              //Initialize the segment visitors
              this.initializeVisitors();
          }
          #endregion
  
          public void initializeVisitors()
          {
              //This replaces terms in no match segments
              this.noMatchVisitor = new TermInjectorTranslationProviderElementTermReplacementVisitor(
                  this.Options,
                  this.exactMatchTrieSource,
                  this.regexTrieSource);
              //This collects terms from current segment source
              this.fuzzyCurrentVisitor = new TermInjectorTranslationProviderElementTermExtractionVisitor(
                  this.Options,
                  this.exactMatchTrieSource,
                  this.regexTrieSource);
              //This collects terms from translation suggestion source
              this.fuzzyMatchVisitor = new TermInjectorTranslationProviderElementTermExtractionVisitor(
                  this.Options,
                  this.exactMatchTrieSource,
                  this.regexTrieSource);
              //This replaces terms in fuzzy match segments
              this.fuzzyReplaceVisitor = new TermInjectorTranslationProviderElementTermReplacementVisitor(
                  this.Options,
                  this.exactMatchTrieReplaces,
                  this.regexTrieReplaces);
          }
  
          #region "ITranslationProvider Members"
          public ITranslationProviderLanguageDirection GetLanguageDirection(LanguagePair languageDirection)
          {
              return new TermInjectorTranslationProviderLanguageDirection(this, languageDirection);
          }
  
          public void loadTM()
          {
              fileTM = new FileBasedTranslationMemory(this.Options.TMFileName);
          }
  
          public FileBasedTranslationMemory FileTM
          {
              get { return this.fileTM; }
          }
  
          public Determiniser<TranslationAndReplacement> Determiniser
          {
              get { return this.determiniser; }
          }
  
          public RegexTrieFactory<TranslationAndReplacement> RegexTrieFactory
          {
              get { return this.regexTrieFactory; }
          }
  
          public Trie ExactMatchTrieSource
          {
              get { return this.exactMatchTrieSource; }
          }
  
          public Trie ExactMatchTrieReplaces
          {
              get { return this.exactMatchTrieReplaces; }
          }
  
          public RegexTrie<TranslationAndReplacement> RegexTrieSource
          {
              get { return this.regexTrieSource; }
          }
  
          public RegexTrie<TranslationAndReplacement> RegexTrieReplaces
          {
  
gt:             get { return this.regexTrieReplaces; }