//usr/bin/env clang++ $0 -o ${o=`mktemp`} -fmodules -fcxx-modules && echo $o && exec $o $* || exit

@import AppKit;

@interface TextView : NSTextView
@end

@implementation TextView
- (id)init
{
    return [self initWithFrame:NSZeroRect];
}

- (id)initWithFrame:(NSRect)rect
{
    if ((self = [super initWithFrame:rect])) {
        [self setFont:[NSFont fontWithName:@"Menlo" size:24.0]];
        [self setTextContainerInset:NSMakeSize(20.0, 20.0)];
        // self.automaticTextCompletionEnabled = YES;
        // self.continuousSpellCheckingEnabled = YES;
    }
    return self;
}


// - (BOOL)hasMarkedText
// {
//     BOOL hasMarked = [super hasMarkedText];
//     NSLog(@"%s %d", __FUNCTION__, hasMarked);
//     return hasMarked;
// }

#if 0
- (NSRange)markedRange
{
    NSRange range = [super markedRange];
    NSLog(@"%s %@", __FUNCTION__, NSStringFromRange(range));
    return range;
}

- (void)unmarkText
{
    NSLog(@"%s", __FUNCTION__);
    [super unmarkText];
}

- (NSRange)selectedRange
{
    NSRange range = [super selectedRange];
    NSLog(@"%s %@", __FUNCTION__, NSStringFromRange(range));
    return range;
}
#endif

- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange
{
    NSRect rect = [super firstRectForCharacterRange:range actualRange:actualRange];
    NSLog(@"%s %@ -> %@ %@", __FUNCTION__, NSStringFromRange(range), NSStringFromRange(*actualRange),
        NSStringFromRect(rect));
    return rect;
}

#if 0
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
{
    NSLog(@"%s %@ replacementRange=%@", __FUNCTION__, aString, NSStringFromRange(replacementRange));
    [super insertText:aString replacementRange:replacementRange];
    NSLog(@"\tdone");
}

- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
{
    NSLog(@"%s %@ selectedRange=%@ replacementRange=%@", __FUNCTION__, aString,
        NSStringFromRange(selectedRange), NSStringFromRange(replacementRange));

    [super setMarkedText:aString selectedRange:selectedRange replacementRange:replacementRange];
    NSLog(@"\tdone");
}

- (NSArray<NSString *> *)validAttributesForMarkedText
{
    auto ret = [super validAttributesForMarkedText];
    NSLog(@"%s attributes=%@", __FUNCTION__, ret);
    return ret;
}

- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range actualRange:(NSRangePointer)actualRange
{
    NSAttributedString *str = [super attributedSubstringForProposedRange:range actualRange:actualRange];
    NSLog(@"%s proposedRange=%@ actualRange=%@ = %@", __FUNCTION__,
        NSStringFromRange(range), actualRange ? NSStringFromRange(*actualRange) : nil, str);
    return str;
}
#endif

@end

int main()
{
    @autoreleasepool {
        [NSApplication sharedApplication];
        [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];

        id appMenu = [[NSMenu new] autorelease];
        [appMenu addItem:[[[NSMenuItem alloc] initWithTitle:@"Quit"
            action:@selector(terminate:) keyEquivalent:@"q"] autorelease]];
        id appMenuItem = [[NSMenuItem new] autorelease];
        [appMenuItem setSubmenu:appMenu];
        NSApp.mainMenu = [[NSMenu new] autorelease];
        [NSApp.mainMenu addItem:appMenuItem];

        for (int i = 0; i < 3; ++i) {
            NSWindow *window = [[[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1000, 70)
                styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable
                backing:NSBackingStoreBuffered defer:YES] autorelease];

            if (i == 0) {
                [window.contentView addSubview:[[TextView alloc] initWithFrame:NSMakeRect(0, 0, 500, 70)]];
                [window.contentView addSubview:[[TextView alloc] initWithFrame:NSMakeRect(500, 0, 500, 70)]];
            } else {
                window.contentView = [[TextView alloc] init];
            }

            [window center];
            [window makeKeyAndOrderFront:nil];
        }

        [NSApp activateIgnoringOtherApps:YES];
        [NSApp run];
        return 0;
    }

}