/*******************************************************
 * Copyright (C) 2018 XMind Ltd. - All Rights Reserved
 *******************************************************/

#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>
#include <napi.h>
#include "./tokenizer.h"

// 辅助函数：将 N-API 字符串转换为 NSString
NSString* ToNSString(const std::string& value) {
  return [[NSString alloc] initWithUTF8String:value.c_str()];
}

static NSLinguisticTagger* _tagger = NULL;
static NSLinguisticTagger* getTagger() {
  if (_tagger == NULL) {
    _tagger = [[NSLinguisticTagger alloc]
      initWithTagSchemes: @[NSLinguisticTagSchemeLemma]
                 options: NSLinguisticTaggerOmitWhitespace | NSLinguisticTaggerJoinNames | NSLinguisticTaggerOmitPunctuation];
  }
  return _tagger;
}

Napi::Value Tokenize(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();

  if (info.Length() != 1 || !info[0].IsString()) {
    Napi::TypeError::New(env, "Invalid arguments").ThrowAsJavaScriptException();
    return env.Undefined();
  }

  std::string inputStr = info[0].As<Napi::String>().Utf8Value();

  @autoreleasepool {
    NSString* input = ToNSString(inputStr);
    NSMutableArray* queryWords = [[NSMutableArray alloc] init];

    NSLinguisticTagger* tagger = getTagger();
    tagger.string = input;

    [tagger enumerateTagsInRange:NSMakeRange(0, input.length)
                          scheme:NSLinguisticTagSchemeLemma
                         options:NSLinguisticTaggerOmitPunctuation | NSLinguisticTaggerOmitWhitespace
                      usingBlock:^(NSLinguisticTag _Nullable tag, NSRange tokenRange, NSRange sentenceRange, BOOL* _Nonnull stop) {

      NSString* word = [input substringWithRange:tokenRange];
      NSString* lemma = nil;

      if (tag != nil && ![tag isEqualToString:word]) {
        lemma = tag;
      }

      NSDictionary* dict = @{
        @"lemma": lemma == nil ? @"" : lemma,
        @"word": word,
        @"start": @(tokenRange.location),
        @"length": @(tokenRange.length)
      };

      [queryWords addObject:dict];
    }];

    // 创建结果数组
    Napi::Array resultArr = Napi::Array::New(env, [queryWords count]);

    for (NSUInteger i = 0; i < [queryWords count]; i++) {
      NSDictionary* resultObj = queryWords[i];
      Napi::Object obj = Napi::Object::New(env);

      obj.Set("lemma", Napi::String::New(env, [((NSString*)[resultObj objectForKey:@"lemma"]) UTF8String]));
      obj.Set("word", Napi::String::New(env, [((NSString*)[resultObj objectForKey:@"word"]) UTF8String]));
      obj.Set("start", Napi::Number::New(env, [((NSNumber*)[resultObj objectForKey:@"start"]) intValue]));
      obj.Set("length", Napi::Number::New(env, [((NSNumber*)[resultObj objectForKey:@"length"]) intValue]));

      resultArr[i] = obj;
    }

    return resultArr;
  }
}