2019-11-15 04:54:34 +00:00
using ReactiveUI ;
2019-11-14 05:28:27 +00:00
using ReactiveUI.Fody.Helpers ;
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Reactive ;
using System.Reactive.Disposables ;
using System.Reactive.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using Wabbajack.Common ;
using Wabbajack.Lib ;
namespace Wabbajack
{
public class MO2CompilerVM : ViewModel , ISubCompilerVM
{
2019-11-16 23:09:13 +00:00
private readonly MO2CompilationSettings settings ;
2019-11-14 05:28:27 +00:00
private readonly ObservableAsPropertyHelper < string > _Mo2Folder ;
public string Mo2Folder = > _Mo2Folder . Value ;
private readonly ObservableAsPropertyHelper < string > _MOProfile ;
public string MOProfile = > _MOProfile . Value ;
public FilePickerVM DownloadLocation { get ; }
public FilePickerVM ModlistLocation { get ; }
public IReactiveCommand BeginCommand { get ; }
private readonly ObservableAsPropertyHelper < bool > _Compiling ;
public bool Compiling = > _Compiling . Value ;
private readonly ObservableAsPropertyHelper < ModlistSettingsEditorVM > _ModlistSettings ;
public ModlistSettingsEditorVM ModlistSettings = > _ModlistSettings . Value ;
public MO2CompilerVM ( CompilerVM parent )
{
this . ModlistLocation = new FilePickerVM ( )
{
DoExistsCheck = true ,
PathType = FilePickerVM . PathTypeOptions . File ,
PromptTitle = "Select Modlist"
} ;
this . DownloadLocation = new FilePickerVM ( )
{
DoExistsCheck = true ,
PathType = FilePickerVM . PathTypeOptions . Folder ,
PromptTitle = "Select Download Location" ,
} ;
this . _Mo2Folder = this . WhenAny ( x = > x . ModlistLocation . TargetPath )
. Select ( loc = >
{
try
{
var profile_folder = Path . GetDirectoryName ( loc ) ;
return Path . GetDirectoryName ( Path . GetDirectoryName ( profile_folder ) ) ;
}
catch ( Exception )
{
return null ;
}
} )
. ToProperty ( this , nameof ( this . Mo2Folder ) ) ;
this . _MOProfile = this . WhenAny ( x = > x . ModlistLocation . TargetPath )
. Select ( loc = >
{
try
{
var profile_folder = Path . GetDirectoryName ( loc ) ;
return Path . GetFileName ( profile_folder ) ;
}
catch ( Exception )
{
return null ;
}
} )
. ToProperty ( this , nameof ( this . MOProfile ) ) ;
// Wire missing Mo2Folder to signal error state for Modlist Location
this . ModlistLocation . AdditionalError = this . WhenAny ( x = > x . Mo2Folder )
. Select < string , IErrorResponse > ( moFolder = >
{
if ( Directory . Exists ( moFolder ) ) return ErrorResponse . Success ;
return ErrorResponse . Fail ( $"MO2 Folder could not be located from the given modlist location.{Environment.NewLine}Make sure your modlist is inside a valid MO2 distribution." ) ;
} ) ;
// Wire start command
this . BeginCommand = ReactiveCommand . CreateFromTask (
canExecute : Observable . CombineLatest (
this . WhenAny ( x = > x . ModlistLocation . InError ) ,
this . WhenAny ( x = > x . DownloadLocation . InError ) ,
resultSelector : ( ml , down ) = > ! ml & & ! down )
. ObserveOnGuiThread ( ) ,
execute : async ( ) = >
{
Compiler compiler ;
try
{
compiler = new Compiler ( this . Mo2Folder )
{
MO2Profile = this . MOProfile ,
ModListName = this . ModlistSettings . ModListName ,
ModListAuthor = this . ModlistSettings . AuthorText ,
ModListDescription = this . ModlistSettings . Description ,
ModListImage = this . ModlistSettings . ImagePath . TargetPath ,
ModListWebsite = this . ModlistSettings . Website ,
ModListReadme = this . ModlistSettings . ReadMeText . TargetPath ,
} ;
}
catch ( Exception ex )
{
while ( ex . InnerException ! = null ) ex = ex . InnerException ;
Utils . Log ( $"Compiler error: {ex.ExceptionToString()}" ) ;
return ;
}
await Task . Run ( ( ) = >
{
try
{
compiler . Compile ( ) ;
}
catch ( Exception ex )
{
while ( ex . InnerException ! = null ) ex = ex . InnerException ;
Utils . Log ( $"Compiler error: {ex.ExceptionToString()}" ) ;
}
} ) ;
} ) ;
this . _Compiling = this . BeginCommand . IsExecuting
. ToProperty ( this , nameof ( this . Compiling ) ) ;
// Load settings
2019-11-16 23:09:13 +00:00
this . settings = parent . MWVM . Settings . Compiler . MO2Compilation ;
2019-11-15 04:54:18 +00:00
this . ModlistLocation . TargetPath = settings . LastCompiledProfileLocation ;
2019-11-14 05:28:27 +00:00
if ( ! string . IsNullOrWhiteSpace ( settings . DownloadLocation ) )
{
this . DownloadLocation . TargetPath = settings . DownloadLocation ;
}
parent . MWVM . Settings . SaveSignal
2019-11-16 23:09:13 +00:00
. Subscribe ( _ = > Unload ( ) )
2019-11-14 05:28:27 +00:00
. DisposeWith ( this . CompositeDisposable ) ;
// Load custom modlist settings per MO2 profile
this . _ModlistSettings = Observable . CombineLatest (
this . WhenAny ( x = > x . ModlistLocation . ErrorState ) ,
this . WhenAny ( x = > x . ModlistLocation . TargetPath ) ,
resultSelector : ( State , Path ) = > ( State , Path ) )
// A short throttle is a quick hack to make the above changes "atomic"
. Throttle ( TimeSpan . FromMilliseconds ( 25 ) )
. Select ( u = >
{
if ( u . State . Failed ) return null ;
var modlistSettings = settings . ModlistSettings . TryCreate ( u . Path ) ;
2019-11-16 22:33:32 +00:00
return new ModlistSettingsEditorVM ( modlistSettings )
{
ModListName = this . MOProfile
} ;
2019-11-14 05:28:27 +00:00
} )
// Interject and save old while loading new
. Pairwise ( )
. Do ( pair = >
{
pair . Previous ? . Save ( ) ;
pair . Current ? . Init ( ) ;
} )
. Select ( x = > x . Current )
// Save to property
. ObserveOnGuiThread ( )
. ToProperty ( this , nameof ( this . ModlistSettings ) ) ;
2019-11-15 04:54:34 +00:00
// If Mo2 folder changes and download location is empty, set it for convenience
this . WhenAny ( x = > x . Mo2Folder )
. DelayInitial ( TimeSpan . FromMilliseconds ( 100 ) )
. Where ( x = > Directory . Exists ( x ) )
. FilterSwitch (
this . WhenAny ( x = > x . DownloadLocation . Exists )
. Invert ( ) )
. Subscribe ( x = >
{
try
{
var tmp_compiler = new Compiler ( this . Mo2Folder ) ;
this . DownloadLocation . TargetPath = tmp_compiler . MO2DownloadsFolder ;
}
catch ( Exception ex )
{
Utils . Log ( $"Error setting default download location {ex}" ) ;
}
} )
. DisposeWith ( this . CompositeDisposable ) ;
2019-11-16 23:09:13 +00:00
}
2019-11-15 04:54:34 +00:00
2019-11-16 23:09:13 +00:00
public void Unload ( )
{
settings . DownloadLocation = this . DownloadLocation . TargetPath ;
settings . LastCompiledProfileLocation = this . ModlistLocation . TargetPath ;
this . ModlistSettings ? . Save ( ) ;
2019-11-14 05:28:27 +00:00
}
}
}