//
// «GLUE_NAME»
// «APP_NAME» «APP_VERSION»
// «FRAMEWORK_NAME» «FRAMEWORK_VERSION»
// «AEBGLUE_COMMAND»
//

#import "«PREFIX»Glue.h"

// TO DO: add comments where -release calls are needed in non-ARC builds


@implementation «PREFIX»Formatter
- (NSString *)propertyByCode:(OSType)code {
    switch (code) {
«+PROPERTY_FORMATTER»
        case «CODE»: return @"«NAME»";
«-PROPERTY_FORMATTER»
        default: return [super propertyByCode: code];
    }
}
- (NSString *)elementsByCode:(OSType)code {
    switch (code) {
«+ELEMENTS_FORMATTER»
        case «CODE»: return @"«NAME»";
«-ELEMENTS_FORMATTER»
        default: return [super elementsByCode: code];
    }
}
- (NSString *)prefix {
    return @"«PREFIX»";
}
@end




@implementation «PREFIX»Symbol
+ (AEBSymbol *)aebSymbolForCode:(OSType)code_ {
    switch (code_) {
«+SYMBOL_SWITCH»
        case «CODE»: return self.«NAME»;
«-SYMBOL_SWITCH»
        default: return [super aebSymbolForCode: code_];
    }
}
// Types/properties 
«+TYPE_SYMBOL»
+ (AEBSymbol *)«NAME» {AEB_RETURN_SYMBOL(@"«NAME»", typeType, «CODE»);}
«-TYPE_SYMBOL»
// Enumerators
«+ENUM_SYMBOL»
+ (AEBSymbol *)«NAME» {AEB_RETURN_SYMBOL(@"«NAME»", typeEnumerated, «CODE»);}
«-ENUM_SYMBOL»
@end



«+COMMAND»

@implementation «PREFIX»«CAP_NAME»Command
«+PARAMETER»
- (instancetype)«NAME»:(id)value {
    [self setParameter: value forKeyword: «CODE»];
    return self;
}
«-PARAMETER»
- (NSString *)aebCommandName {
    return @"«COMMAND_NAME»";
}
- (NSString *)aebParameterNameForCode:(DescType)code {
    switch (code) {
«+PARAMETER»
        case «CODE»: return @"«NAME»";
«-PARAMETER»
    }
    return [super aebParameterNameForCode: code];
}
@end
«-COMMAND»




@implementation «PREFIX»Specifier
- (NSString *)description {
    return [«PREFIX»Formatter formatObject: self.aemQuery appData: self.aebAppData];
}
// Properties
«+PROPERTY_SPECIFIER»
- (instancetype)«NAME» {
    return [[self.class alloc] initWithAppData: self.aebAppData
                                      aemQuery: [(AEMObjectSpecifier *)self.aemQuery property: «CODE»]];
}
«-PROPERTY_SPECIFIER»
// Elements
«+ELEMENTS_SPECIFIER»
- (instancetype)«NAME» {
    return [[self.class alloc] initWithAppData: self.aebAppData
                                      aemQuery: [(AEMObjectSpecifier *)self.aemQuery elements: «CODE»]];
}
«-ELEMENTS_SPECIFIER»
// Commands
«+COMMAND»
- («PREFIX»«CAP_NAME»Command *)«COMMAND_NAME» {
    return [«PREFIX»«CAP_NAME»Command commandWithAppData: self.aebAppData
                       eventClass: «EVENT_CLASS»
                          eventID: «EVENT_ID»
                  directParameter: (__bridge id)kAEBNoDirectParameter
                      parentQuery: self.aemQuery];
}
- («PREFIX»«CAP_NAME»Command *)«COMMAND_NAME»:(id)directParameter {
    return [«PREFIX»«CAP_NAME»Command commandWithAppData: self.aebAppData
                       eventClass: «EVENT_CLASS»
                          eventID: «EVENT_ID»
                  directParameter: directParameter
                      parentQuery: self.aemQuery];
}
«-COMMAND»
@end




@implementation «PREFIX»Application

/* note: clients shouldn't need to call -initWithTargetType:data: themselves */

- (instancetype)initWithTargetType:(AEBTargetType)targetType_ data:(id)targetData_ {
    AEBStaticAppData *data = [[AEBStaticAppData alloc] initWithTargetType: targetType_
                                                               targetData: targetData_
                                                            launchOptions: kAEMDefaultLaunchOptions
                                                             relaunchMode: AEBRelaunchLimited
                                                           specifierClass: «PREFIX»Specifier.class
                                                              symbolClass: «PREFIX»Symbol.class]; // non-ARC: add autorelease
    return [super initWithAppData: data aemQuery: AEMApp];
}

/* initialisers */

+ (instancetype)application {
    return [[self alloc] init];
}
+ (instancetype)currentApplication {
    return [[self alloc] initCurrentApplication]; // non-ARC: add autorelease
}
+ (instancetype)applicationWithName:(NSString *)name {
    return [[self alloc] initWithName: name]; // non-ARC: add autorelease
}
+ (instancetype)applicationWithURL:(NSURL *)url {
    return [[self alloc] initWithURL: url]; // non-ARC: add autorelease
}
+ (instancetype)applicationWithBundleID:(NSString *)bundleID {
    return [[self alloc] initWithBundleID: bundleID]; // non-ARC: add autorelease
}
+ (instancetype)applicationWithProcessID:(pid_t)pid {
    return [[self alloc] initWithProcessID: pid]; // non-ARC: add autorelease
}
+ (instancetype)applicationWithDescriptor:(NSAppleEventDescriptor *)desc {
    return [[self alloc] initWithDescriptor: desc]; // non-ARC: add autorelease
}
- (instancetype)init {
    return [self initWithBundleID: @"«BUNDLE_ID»"];
}
- (instancetype)initCurrentApplication {
    return [self initWithTargetType: AEBTargetCurrent data: nil];
}
- (instancetype)initWithName:(NSString *)name {
    return [self initWithTargetType: AEBTargetName data: name];
}
- (instancetype)initWithURL:(NSURL *)url {
    return [self initWithTargetType: AEBTargetURL data: url];
}
- (instancetype)initWithBundleID:(NSString *)bundleID {
    return [self initWithTargetType: AEBTargetBundleID data: bundleID];
}
- (instancetype)initWithProcessID:(pid_t)pid {
    return [self initWithTargetType: AEBTargetProcessID data: [NSNumber numberWithInteger: pid]];
}
- (instancetype)initWithDescriptor:(NSAppleEventDescriptor *)desc {
    return [self initWithTargetType: AEBTargetDescriptor data: desc];
}

/* misc */

- («PREFIX»Specifier *)customRoot:(id)object {
    if ([object isKindOfClass: «PREFIX»Specifier.class]) {
        return [[«PREFIX»Specifier alloc] initWithAppData: self.aebAppData aemQuery: [object aemQuery]]; // non-ARC: add autorelease
    } else if ([object isKindOfClass: AEMQuery.class]) {
        return [[«PREFIX»Specifier alloc] initWithAppData: self.aebAppData aemQuery: object];  // non-ARC: add autorelease
    } else if (!object) {
        return [[«PREFIX»Specifier alloc] initWithAppData: self.aebAppData aemQuery: AEMApp];  // non-ARC: add autorelease
    } else {
        return [[«PREFIX»Specifier alloc] initWithAppData: self.aebAppData aemQuery: AEMRoot(object)]; // non-ARC: add autorelease
    }
}
@end

