2019-08-07 23:06:38 +00:00
using SevenZipExtractor ;
using System ;
2019-07-22 22:17:46 +00:00
using System.Collections.Generic ;
using System.Collections.ObjectModel ;
2019-07-30 21:45:04 +00:00
using System.ComponentModel ;
2019-07-22 22:17:46 +00:00
using System.IO ;
using System.Reflection ;
using System.Threading ;
2019-07-31 03:59:19 +00:00
using System.Windows ;
using System.Windows.Input ;
2019-07-22 22:17:46 +00:00
using System.Windows.Threading ;
using Wabbajack.Common ;
namespace Wabbajack
{
2019-07-30 21:45:04 +00:00
internal class AppState : INotifyPropertyChanged
2019-07-22 22:17:46 +00:00
{
public class CPUStatus
{
public int Progress { get ; internal set ; }
public string Msg { get ; internal set ; }
public int ID { get ; internal set ; }
}
public volatile bool Dirty ;
private Dispatcher dispatcher ;
2019-07-30 21:45:04 +00:00
public event PropertyChangedEventHandler PropertyChanged ;
public void OnPropertyChanged ( string name )
{
PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( name ) ) ;
}
2019-07-22 22:17:46 +00:00
public ObservableCollection < string > Log { get ; }
public ObservableCollection < CPUStatus > Status { get ; }
2019-07-30 21:45:04 +00:00
private string _mode ;
public string Mode
{
get
{
return _mode ;
}
set
{
_mode = value ;
OnPropertyChanged ( "Mode" ) ;
}
}
2019-08-07 23:06:38 +00:00
private bool _ignoreMissingFiles = false ;
public bool IgnoreMissingFiles
{
get
{
return _ignoreMissingFiles ;
}
set
{
if ( value )
{
if ( MessageBox . Show ( "Setting this value could result in broken installations. \n Are you sure you want to continue?" , "Ignore Missing Files?" , MessageBoxButton . OKCancel , MessageBoxImage . Warning )
= = MessageBoxResult . OK )
{
_ignoreMissingFiles = value ;
}
}
else
{
_ignoreMissingFiles = value ;
}
OnPropertyChanged ( "IgnoreMissingFiles" ) ;
}
}
2019-07-31 03:59:19 +00:00
private string _mo2Folder ;
2019-07-30 21:45:04 +00:00
private string _modListName ;
2019-07-31 03:59:19 +00:00
private ModList _modList ;
private string _location ;
2019-07-30 21:45:04 +00:00
public string ModListName
{
get
{
return _modListName ;
}
set
{
_modListName = value ;
OnPropertyChanged ( "ModListName" ) ;
}
}
2019-07-31 03:59:19 +00:00
public string Location
{
get
{
return _location ;
}
set
{
_location = value ;
OnPropertyChanged ( "Location" ) ;
}
}
2019-08-02 23:04:04 +00:00
private int _queueProgress ;
public int QueueProgress
{
get
{
return _queueProgress ;
}
set
{
if ( value ! = _queueProgress )
{
_queueProgress = value ;
OnPropertyChanged ( "QueueProgress" ) ;
}
}
}
2019-07-22 22:17:46 +00:00
private List < CPUStatus > InternalStatus { get ; }
public string LogFile { get ; private set ; }
public AppState ( Dispatcher d , String mode )
{
2019-08-20 21:44:32 +00:00
_startTime = DateTime . Now ;
2019-08-07 23:06:38 +00:00
ArchiveFile . SetupLibrary ( ) ;
2019-07-22 22:17:46 +00:00
LogFile = Assembly . GetExecutingAssembly ( ) . Location + ".log" ;
if ( LogFile . FileExists ( ) )
File . Delete ( LogFile ) ;
Mode = mode ;
Dirty = false ;
dispatcher = d ;
Log = new ObservableCollection < string > ( ) ;
Status = new ObservableCollection < CPUStatus > ( ) ;
InternalStatus = new List < CPUStatus > ( ) ;
var th = new Thread ( ( ) = > UpdateLoop ( ) ) ;
th . Priority = ThreadPriority . BelowNormal ;
th . IsBackground = true ;
th . Start ( ) ;
}
private void UpdateLoop ( )
{
while ( true )
{
if ( Dirty )
{
lock ( InternalStatus )
{
var data = InternalStatus . ToArray ( ) ;
dispatcher . Invoke ( ( ) = >
{
for ( int idx = 0 ; idx < data . Length ; idx + = 1 )
{
if ( idx > = Status . Count )
Status . Add ( data [ idx ] ) ;
else if ( Status [ idx ] ! = data [ idx ] )
Status [ idx ] = data [ idx ] ;
}
} ) ;
Dirty = false ;
}
}
2019-07-23 04:27:26 +00:00
Thread . Sleep ( 1000 ) ;
2019-07-22 22:17:46 +00:00
}
}
2019-07-31 03:59:19 +00:00
internal void ConfigureForInstall ( string modlist )
{
_modList = modlist . FromJSONString < ModList > ( ) ;
Mode = "Installing" ;
ModListName = _modList . Name ;
Location = Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) ;
}
2019-07-22 22:17:46 +00:00
public void LogMsg ( string msg )
{
2019-08-20 21:44:32 +00:00
msg = $"{(DateTime.Now - _startTime).TotalSeconds:0.##} - {msg}" ;
2019-07-22 22:17:46 +00:00
dispatcher . Invoke ( ( ) = > Log . Add ( msg ) ) ;
lock ( dispatcher ) {
File . AppendAllText ( LogFile , msg + "\r\n" ) ;
}
}
public void SetProgress ( int id , string msg , int progress )
{
lock ( InternalStatus )
{
Dirty = true ;
while ( id > = InternalStatus . Count )
{
InternalStatus . Add ( new CPUStatus ( ) ) ;
}
InternalStatus [ id ] = new CPUStatus ( ) { ID = id , Msg = msg , Progress = progress } ;
}
}
2019-07-31 03:59:19 +00:00
2019-08-02 23:04:04 +00:00
public void SetQueueSize ( int max , int current )
{
2019-08-22 22:05:16 +00:00
if ( max = = 0 )
max = 1 ;
2019-08-02 23:04:04 +00:00
var total = current * 100 / max ;
QueueProgress = total ;
}
2019-07-31 03:59:19 +00:00
private ICommand _changePath ;
public ICommand ChangePath
{
get
{
if ( _changePath = = null )
{
_changePath = new LambdaCommand ( ( ) = > true , ( ) = > this . ExecuteChangePath ( ) ) ;
}
return _changePath ;
}
}
private void ExecuteChangePath ( )
{
if ( Mode = = "Installing" )
{
var ofd = new Ookii . Dialogs . Wpf . VistaFolderBrowserDialog ( ) ;
ofd . Description = "Select Installation Directory" ;
ofd . UseDescriptionForTitle = true ;
if ( ofd . ShowDialog ( ) = = true )
{
Location = ofd . SelectedPath ;
}
}
else
{
var fsd = new Ookii . Dialogs . Wpf . VistaOpenFileDialog ( ) ;
fsd . Title = "Select a ModOrganizer modlist.txt file" ;
fsd . Filter = "modlist.txt|modlist.txt" ;
if ( fsd . ShowDialog ( ) = = true )
{
Location = fsd . FileName ;
ConfigureForBuild ( ) ;
}
}
}
private void ConfigureForBuild ( )
{
var profile_folder = Path . GetDirectoryName ( Location ) ;
var mo2folder = Path . GetDirectoryName ( Path . GetDirectoryName ( profile_folder ) ) ;
if ( ! File . Exists ( Path . Combine ( mo2folder , "ModOrganizer.exe" ) ) )
LogMsg ( $"Error! No ModOrganizer2.exe found in {mo2folder}" ) ;
var profile_name = Path . GetFileName ( profile_folder ) ;
ModListName = profile_name ;
Mode = "Building" ;
_mo2Folder = mo2folder ;
}
private ICommand _begin ;
2019-08-20 21:44:32 +00:00
private DateTime _startTime ;
2019-07-31 03:59:19 +00:00
public ICommand Begin
{
get
{
if ( _begin = = null )
{
_begin = new LambdaCommand ( ( ) = > true , ( ) = > this . ExecuteBegin ( ) ) ;
}
return _begin ;
}
}
private void ExecuteBegin ( )
{
if ( Mode = = "Installing" )
{
var installer = new Installer ( _modList , Location , msg = > this . LogMsg ( msg ) ) ;
2019-08-07 23:06:38 +00:00
installer . IgnoreMissingFiles = IgnoreMissingFiles ;
2019-07-31 03:59:19 +00:00
var th = new Thread ( ( ) = >
{
try
{
installer . Install ( ) ;
}
2019-08-02 22:31:13 +00:00
catch ( Exception ex )
{
2019-08-22 22:05:16 +00:00
while ( ex . InnerException ! = null ) ex = ex . InnerException ;
2019-08-07 23:06:38 +00:00
LogMsg ( ex . StackTrace ) ;
2019-08-22 23:29:44 +00:00
LogMsg ( ex . ToString ( ) ) ;
2019-08-02 22:31:13 +00:00
LogMsg ( $"{ex.Message} - Can't continue" ) ;
2019-07-31 03:59:19 +00:00
}
} ) ;
th . Priority = ThreadPriority . BelowNormal ;
th . Start ( ) ;
}
else
{
var compiler = new Compiler ( _mo2Folder , msg = > LogMsg ( msg ) ) ;
2019-08-07 23:06:38 +00:00
compiler . IgnoreMissingFiles = IgnoreMissingFiles ;
2019-07-31 03:59:19 +00:00
compiler . MO2Profile = ModListName ;
var th = new Thread ( ( ) = >
{
2019-08-07 23:06:38 +00:00
try
{
compiler . Compile ( ) ;
}
catch ( Exception ex )
{
2019-08-22 22:05:16 +00:00
while ( ex . InnerException ! = null ) ex = ex . InnerException ;
2019-08-07 23:06:38 +00:00
LogMsg ( ex . StackTrace ) ;
2019-08-22 23:29:44 +00:00
LogMsg ( ex . ToString ( ) ) ;
2019-08-07 23:06:38 +00:00
LogMsg ( $"{ex.Message} - Can't continue" ) ;
}
2019-07-31 03:59:19 +00:00
} ) ;
th . Priority = ThreadPriority . BelowNormal ;
th . Start ( ) ;
}
}
2019-07-22 22:17:46 +00:00
}
}