text: ﻿using RuriLib;
  using RuriLib.Interfaces;
  using RuriLib.ViewModels;
  using System;
  using System.Collections.Generic;
  using System.Collections.ObjectModel;
  using System.IO;
  using System.Threading.Tasks;
  using System.Windows;
  using System.Windows.Data;
  
  namespace OpenBullet
  {
      public enum Components
      {
          Main,
          RunnerManager,
          Runner,
          ProxyManager,
          WordlistManager,
          HitsDB,
          ConfigManager,
          Stacker,
          OtherOptions,
          Settings,
          ListGenerator,
          SeleniumTools,
          Database,
          About,
          Unknown
      }
  
      public class LoggerViewModel : ViewModelBase, ILogger
      {
          public ObservableCollection<LogEntry> EntriesCollection { get; set; }
  
          public IEnumerable<LogEntry> Entries => EntriesCollection;
  
          public bool Enabled
          {
              get
              {
                  try
                  {
                      // The settings might be null
                      return OB.OBSettings.General.EnableLogging;
                  }
                  catch
                  {
                      return false;
                  }
              }
          }
  
          public int BufferSize
          {
              get
              {
                  try
                  {
                      // The settings might be null
                      return OB.OBSettings.General.LogBufferSize;
                  }
                  catch
                  {
                      return 0;
                  }
              }
          }
  
          public LoggerViewModel()
          {
              EntriesCollection = new ObservableCollection<LogEntry>();
  
              CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(EntriesCollection);
              view.Filter = ErrorFilter;
          }
  
          public void Refresh()
          {
              try
              {
                  CollectionViewSource.GetDefaultView(EntriesCollection).Refresh();
              }
              catch { }
          }
  
          #region Filters
          private bool onlyErrors = false;
          public bool OnlyErrors { get { return onlyErrors; } set { onlyErrors = value; OnPropertyChanged(); Refresh(); } }
          
          private string searchString = "";
          public string SearchString { get { return searchString; } set { searchString = value; OnPropertyChanged(); } }
  
          private bool ErrorFilter(object item)
          {
              // If search box not empty, filter out all the stuff that's not needed
              if (SearchString != string.Empty)
              {
                  if (!(item as LogEntry).LogString.ToLower().Contains(SearchString.ToLower()))
                      return false;
              }
  
              if (!OB.Logger.OnlyErrors)
                  return true;
  
              else
                  return ((item as LogEntry).LogLevel == LogLevel.Error);
          }
          #endregion
  
          public void Log(string message, LogLevel level, bool prompt = false, int timeout = 0)
          {
              Log(Components.Unknown, level, message, prompt, timeout);
          }
  
          public void Log(Components component, LogLevel level, string message, bool prompt = false, int timeout = 0)
          {
              if (prompt)
              {
                  if (timeout == 0)
                  {
                      MessageBox.Show(message, level.ToString());
                  }
                  else
                  {
                      var w = new System.Windows.Forms.Form() { Size = new System.Drawing.Size(0, 0) };
                      Task.Delay(TimeSpan.FromSeconds(timeout))
                          .ContinueWith((t) => w.Close(), TaskScheduler.FromCurrentSynchronizationContext());
  
                      System.Windows.Forms.MessageBox.Show(w, message, level.ToString());
                  }
              }
  
              if (!Enabled)
              {
                  return;
              }
  
              App.Current.Dispatcher.Invoke(new Action(() =>
              {
                  var entry = new LogEntry(component.ToString(), message, level);
                  InsertEntry(entry);
                  LogToFile(entry);
              }));
          }
  
          public void LogInfo(Components component, string message, bool prompt = false, int timeout = 0)
          {
              Log(component, LogLevel.Info, message, prompt, timeout);
          }
  
          public void LogWarning(Components component, string message, bool prompt = false, int timeout = 0)
          {
              Log(component, LogLevel.Warning, message, prompt, timeout);
          }
  
          public void LogError(Components component, string message, bool prompt = false, int timeout = 0)
          {
              Log(component, LogLevel.Error, message, prompt, timeout);
          }
  
          private void InsertEntry(LogEntry entry)
          {
              try
              {
                  EntriesCollection.Insert(0, entry);
  
                  var count = EntriesCollection.Count;
                  if (count > BufferSize)
                  {
                      EntriesCollection.RemoveAt(count - 1);
                  }
              }
              catch { }
          }
  
          private static void LogToFile(LogEntry entry)
          {
              try
              {
                  if (OB.OBSettings.General.LogToFile)
                  {
                      File.AppendAllText(OB.logFile, $"[{entry.LogTime}] ({entry.LogLevel}) {entry.LogComponent} - " + entry.LogString + Environment.NewLine);
                  }
              }
              catch { }
          }
      }
  }
  