//-----------------------------------------------------------------------------
// Project     : VST SDK
//
// Category    : Helpers
// Filename    : public.sdk/source/vst/interappaudio/VSTInterAppAudioAppDelegateBase.mm
// Created by  : Steinberg, 08/2013.
// Description : VST 3 InterAppAudio
// Flags       : clang-format SMTGSequencer
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------

#import "VSTInterAppAudioAppDelegateBase.h"
#import "public.sdk/source/vst/interappaudio/AudioIO.h"
#import "public.sdk/source/vst/interappaudio/HostApp.h"
#import "public.sdk/source/vst/interappaudio/MidiIO.h"
#import "public.sdk/source/vst/interappaudio/VST3Editor.h"
#import "public.sdk/source/vst/interappaudio/VST3Plugin.h"

using namespace Steinberg::Vst::InterAppAudio;

//------------------------------------------------------------------------
static OSType fourCharCodeToOSType (NSString* inCode)
{
	OSType rval = 0;
	NSData* data = [inCode dataUsingEncoding:NSMacOSRomanStringEncoding];
	[data getBytes:&rval length:sizeof (rval)];
	HTONL (rval);
	return rval;
}

//------------------------------------------------------------------------
@interface VSTInterAppAudioAppDelegateBase ()
//------------------------------------------------------------------------
{
	VST3Plugin plugin;
	VST3Editor editor;

	BOOL audioIOInitialized;
}
@end

//------------------------------------------------------------------------
@implementation VSTInterAppAudioAppDelegateBase
//------------------------------------------------------------------------

//------------------------------------------------------------------------
- (BOOL)initAudioIO
{
	id auArray = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"AudioComponents"];
	if (auArray)
	{
		id desc = [auArray objectAtIndex:0];
		if (desc)
		{
			NSString* typeStr = [desc objectForKey:@"type"];
			NSString* subtypeStr = [desc objectForKey:@"subtype"];
			NSString* manufacturerStr = [desc objectForKey:@"manufacturer"];
			NSString* nameStr = [desc objectForKey:@"name"];
			if (typeStr && subtypeStr && manufacturerStr && nameStr)
			{
				OSType type = fourCharCodeToOSType (typeStr);
				OSType subtype = fourCharCodeToOSType (subtypeStr);
				OSType manufacturer = fourCharCodeToOSType (manufacturerStr);
				AudioIO* audioIO = AudioIO::instance ();
				if (audioIO->init (type, subtype, manufacturer, (__bridge CFStringRef)nameStr) ==
				    Steinberg::kResultTrue)
				{
					if (plugin.init ())
					{
						InterAppAudioHostApp::instance ()->setPlugin (&plugin);
						audioIO->addProcessor (&plugin);
						audioIOInitialized = YES;
						return YES;
					}
				}
			}
		}
	}
	return NO;
}

//------------------------------------------------------------------------
- (BOOL)createUI
{
	if (audioIOInitialized)
	{
		[UIApplication sharedApplication].statusBarHidden = YES;
		self.window = [UIWindow new];
		self.window.backgroundColor = [UIColor redColor];
		CGRect screenSize = self.window.bounds;

		if (editor.init (screenSize))
		{
			self.window.rootViewController = editor.getViewController ();
			[self.window makeKeyAndVisible];
			if (editor.attach (plugin.getEditController ()) == false)
			{
				return NO;
			}
		}
		return YES;
	}
	return NO;
}

//------------------------------------------------------------------------
- (void)savePluginState:(NSCoder*)coder
{
	NSData* processorState = plugin.getProcessorState ();
	NSData* controllerState = plugin.getControllerState ();
	if (processorState)
		[coder encodeObject:processorState forKey:@"VST3ProcessorState"];
	if (controllerState)
		[coder encodeObject:controllerState forKey:@"VST3ControllerState"];
}

//------------------------------------------------------------------------
- (void)restorePluginState:(NSCoder*)coder
{
	NSData* processorState = [coder decodeObjectForKey:@"VST3ProcessorState"];
	if (processorState)
	{
		plugin.setProcessorState (processorState);
	}
	NSData* controllerState = [coder decodeObjectForKey:@"VST3ControllerState"];
	if (controllerState)
	{
		plugin.setControllerState (controllerState);
	}
}

//------------------------------------------------------------------------
// UIApplicationDelegate methods
//------------------------------------------------------------------------
- (BOOL)application:(UIApplication*)application
    willFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
	return [self initAudioIO];
}

//------------------------------------------------------------------------
- (BOOL)application:(UIApplication*)application
    didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
	BOOL result = [self createUI];
	if (result)
	{
		AudioIO::instance ()->start ();
	}
	return result;
}

//------------------------------------------------------------------------
- (BOOL)application:(UIApplication*)application shouldSaveApplicationState:(NSCoder*)coder
{
	[self savePluginState:coder];
	[coder encodeBool:MidiIO::instance ().isEnabled () forKey:@"MIDI Enabled"];
	return YES;
}

//------------------------------------------------------------------------
- (BOOL)application:(UIApplication*)application shouldRestoreApplicationState:(NSCoder*)coder
{
	[self restorePluginState:coder];
	BOOL midiEnabled = [coder decodeBoolForKey:@"MIDI Enabled"];
	MidiIO::instance ().setEnabled (midiEnabled);
	return YES;
}

//------------------------------------------------------------------------
- (void)applicationDidBecomeActive:(UIApplication*)application
{
	AudioIO* audioIO = AudioIO::instance ();
	audioIO->start ();
}

//------------------------------------------------------------------------
- (void)applicationWillResignActive:(UIApplication*)application
{
	AudioIO* audioIO = AudioIO::instance ();
	if (audioIO->getInterAppAudioConnected () == false && MidiIO::instance ().isEnabled () == false)
	{
		audioIO->stop ();
	}
}

@end
