// src/js/newSdk/model/dbTools.ts
async function getCurrentIDBVersion(name) {
  const dbs = await indexedDB.databases();
  const db = dbs.find((db2) => db2.name === name);
  if (db) {
    return db.version;
  }
}

// src/js/newSdk/model/participleSearch/SearchModel.ts
var SearchModel = class {
  constructor() {
    this.db = void 0;
  }
  async init(options) {
    const { ak, env, userId } = options;
    const dbName = `${ak}/${env}/${userId}/participle`;
    const dbVersion = 2;
    if (await getCurrentIDBVersion(dbName) === 1) {
      indexedDB.deleteDatabase(dbName);
      return;
    }
    const dbRequest = indexedDB.open(dbName, dbVersion);
    return new Promise((resolve, reject) => {
      dbRequest.onerror = function(event) {
        reject(event);
      };
      dbRequest.onsuccess = () => {
        this.db = dbRequest.result;
        resolve("");
      };
      dbRequest.onupgradeneeded = (ev) => {
        const db = dbRequest.result;
        const store = db.createObjectStore("participle", {
          keyPath: "_id",
          autoIncrement: true
        });
        store.createIndex("seq", "seq");
        store.createIndex("words", "words");
        store.createIndex("mid", "mid");
        db.createObjectStore("keyValue", {
          keyPath: "_id"
        }).add({
          _id: "participleSequence",
          value: 0
        });
      };
    });
  }
  async getValue(words) {
    const store = this.db.transaction("participle").objectStore("participle");
    const index = store?.index("words");
    const request = index?.getAll(words);
    return new Promise((resolve, reject) => {
      request.onsuccess = (event) => {
        resolve(event.target.result ?? []);
      };
      request.onerror = (event) => {
        reject(event);
      };
    });
  }
  async getByWords(words, pageSize, page) {
    const store = this.db.transaction("participle").objectStore("participle");
    const index = store?.index("words");
    const request = index?.openCursor(IDBKeyRange.only(words));
    const start = pageSize * (page - 1);
    const end = pageSize * page;
    return new Promise((resolve, reject) => {
      const result = [];
      let current = 0;
      request.onsuccess = (event) => {
        const cursor = event.target.result;
        if (cursor) {
          if (current >= start && current < end) {
            result.push(cursor.value);
          }
          current++;
          cursor.continue();
        } else {
          resolve(result);
        }
      };
      request.onerror = (event) => {
        reject(event);
      };
    });
  }
  getCacheParticipleSequence() {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(["keyValue"], "readwrite");
      const store = transaction.objectStore("keyValue");
      const request = store?.get("participleSequence");
      request.onsuccess = (event) => {
        resolve(event.target.result?.value);
      };
      request.onerror = (event) => {
        reject(event);
      };
    });
  }
  setCacheParticipleSequence(seq) {
    if (seq === void 0) {
      console.log("setCacheParticipleSequence seq is undefined");
      return;
    }
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(["keyValue"], "readwrite");
      const store = transaction.objectStore("keyValue");
      const request = store?.put({ _id: "participleSequence", value: seq });
      request.onsuccess = (event) => {
        resolve(event.target.result?.value);
      };
      request.onerror = (event) => {
        reject(event);
      };
    });
  }
  addWord(data, updateSequence = true) {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(["participle", "keyValue"], "readwrite");
      const store = transaction.objectStore("participle");
      store?.add(data);
      if (updateSequence) {
        const store2 = transaction.objectStore("keyValue");
        store2?.put({ _id: "participleSequence", value: data.seq });
      }
      transaction.oncomplete = () => {
        resolve("");
      };
      transaction.onerror = (event) => {
        reject(event);
      };
    });
  }
  removeByseq(seq) {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(["participle"], "readwrite");
      const store = transaction.objectStore("participle");
      const request = store?.openCursor(IDBKeyRange.only(seq));
      request.onsuccess = (event) => {
        const cursor = event.target.result;
        if (cursor) {
          cursor.delete();
          cursor.continue();
        } else {
          resolve("");
        }
      };
      request.onerror = (event) => {
        reject(event);
      };
    });
  }
};
var searchModelInstance = new SearchModel();

// src/workers/participle.ts
var wasm;
var heap = new Array(128).fill(void 0);
heap.push(void 0, null, true, false);
function getObject(idx) {
  return heap[idx];
}
var heap_next = heap.length;
function dropObject(idx) {
  if (idx < 132)
    return;
  heap[idx] = heap_next;
  heap_next = idx;
}
function takeObject(idx) {
  const ret = getObject(idx);
  dropObject(idx);
  return ret;
}
var cachedTextDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-8", { ignoreBOM: true, fatal: true }) : {
  decode: () => {
    throw Error("TextDecoder not available");
  }
};
if (typeof TextDecoder !== "undefined") {
  cachedTextDecoder.decode();
}
var cachedUint8Memory0 = null;
function getUint8Memory0() {
  if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
    cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
  }
  return cachedUint8Memory0;
}
function getStringFromWasm0(ptr, len) {
  ptr = ptr >>> 0;
  return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
function addHeapObject(obj) {
  if (heap_next === heap.length)
    heap.push(heap.length + 1);
  const idx = heap_next;
  heap_next = heap[idx];
  heap[idx] = obj;
  return idx;
}
function debugString(val) {
  const type = typeof val;
  if (type == "number" || type == "boolean" || val == null) {
    return `${val}`;
  }
  if (type == "string") {
    return `"${val}"`;
  }
  if (type == "symbol") {
    const description = val.description;
    if (description == null) {
      return "Symbol";
    } else {
      return `Symbol(${description})`;
    }
  }
  if (type == "function") {
    const name = val.name;
    if (typeof name == "string" && name.length > 0) {
      return `Function(${name})`;
    } else {
      return "Function";
    }
  }
  if (Array.isArray(val)) {
    const length = val.length;
    let debug = "[";
    if (length > 0) {
      debug += debugString(val[0]);
    }
    for (let i = 1; i < length; i++) {
      debug += ", " + debugString(val[i]);
    }
    debug += "]";
    return debug;
  }
  const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
  let className;
  if (builtInMatches.length > 1) {
    className = builtInMatches[1];
  } else {
    return toString.call(val);
  }
  if (className == "Object") {
    try {
      return "Object(" + JSON.stringify(val) + ")";
    } catch (_) {
      return "Object";
    }
  }
  if (val instanceof Error) {
    return `${val.name}: ${val.message}
${val.stack}`;
  }
  return className;
}
var WASM_VECTOR_LEN = 0;
var cachedTextEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder("utf-8") : {
  encode: () => {
    throw Error("TextEncoder not available");
  }
};
var encodeString = typeof cachedTextEncoder.encodeInto === "function" ? function(arg, view) {
  return cachedTextEncoder.encodeInto(arg, view);
} : function(arg, view) {
  const buf = cachedTextEncoder.encode(arg);
  view.set(buf);
  return {
    read: arg.length,
    written: buf.length
  };
};
function passStringToWasm0(arg, malloc, realloc) {
  if (realloc === void 0) {
    const buf = cachedTextEncoder.encode(arg);
    const ptr2 = malloc(buf.length, 1) >>> 0;
    getUint8Memory0().subarray(ptr2, ptr2 + buf.length).set(buf);
    WASM_VECTOR_LEN = buf.length;
    return ptr2;
  }
  let len = arg.length;
  let ptr = malloc(len, 1) >>> 0;
  const mem = getUint8Memory0();
  let offset = 0;
  for (; offset < len; offset++) {
    const code = arg.charCodeAt(offset);
    if (code > 127)
      break;
    mem[ptr + offset] = code;
  }
  if (offset !== len) {
    if (offset !== 0) {
      arg = arg.slice(offset);
    }
    ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
    const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
    const ret = encodeString(arg, view);
    offset += ret.written;
  }
  WASM_VECTOR_LEN = offset;
  return ptr;
}
var cachedInt32Memory0 = null;
function getInt32Memory0() {
  if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
    cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
  }
  return cachedInt32Memory0;
}
var cachedUint32Memory0 = null;
function getUint32Memory0() {
  if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) {
    cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer);
  }
  return cachedUint32Memory0;
}
function getArrayJsValueFromWasm0(ptr, len) {
  ptr = ptr >>> 0;
  const mem = getUint32Memory0();
  const slice = mem.subarray(ptr / 4, ptr / 4 + len);
  const result = [];
  for (let i = 0; i < slice.length; i++) {
    result.push(takeObject(slice[i]));
  }
  return result;
}
function cutForSearch(text, hmm) {
  try {
    const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
    const ptr0 = passStringToWasm0(text, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
    const len0 = WASM_VECTOR_LEN;
    wasm.cutForSearch(retptr, ptr0, len0, hmm);
    var r0 = getInt32Memory0()[retptr / 4 + 0];
    var r1 = getInt32Memory0()[retptr / 4 + 1];
    var v2 = getArrayJsValueFromWasm0(r0, r1).slice();
    wasm.__wbindgen_free(r0, r1 * 4);
    return v2;
  } finally {
    wasm.__wbindgen_add_to_stack_pointer(16);
  }
}
var TokenizeMode = Object.freeze({ Default: 0, "0": "Default", Search: 1, "1": "Search" });
async function __wbg_load(module, imports) {
  if (typeof Response === "function" && module instanceof Response) {
    if (typeof WebAssembly.instantiateStreaming === "function") {
      try {
        return await WebAssembly.instantiateStreaming(module, imports);
      } catch (e) {
        if (module.headers.get("Content-Type") != "application/wasm") {
          console.warn(
            "`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",
            e
          );
        } else {
          throw e;
        }
      }
    }
    const bytes = await module.arrayBuffer();
    return await WebAssembly.instantiate(bytes, imports);
  } else {
    const instance = await WebAssembly.instantiate(module, imports);
    if (instance instanceof WebAssembly.Instance) {
      return { instance, module };
    } else {
      return instance;
    }
  }
}
function __wbg_get_imports() {
  const imports = {};
  imports.wbg = {};
  imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
    takeObject(arg0);
  };
  imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
    const ret = getStringFromWasm0(arg0, arg1);
    return addHeapObject(ret);
  };
  imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
    const ret = getObject(arg0);
    return addHeapObject(ret);
  };
  imports.wbg.__wbindgen_error_new = function(arg0, arg1) {
    const ret = new Error(getStringFromWasm0(arg0, arg1));
    return addHeapObject(ret);
  };
  imports.wbg.__wbindgen_number_new = function(arg0) {
    const ret = arg0;
    return addHeapObject(ret);
  };
  imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) {
    const ret = BigInt.asUintN(64, arg0);
    return addHeapObject(ret);
  };
  imports.wbg.__wbg_set_841ac57cff3d672b = function(arg0, arg1, arg2) {
    getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
  };
  imports.wbg.__wbg_new_b51585de1b234aff = function() {
    const ret = new Object();
    return addHeapObject(ret);
  };
  imports.wbg.__wbg_new_abda76e883ba8a5f = function() {
    const ret = new Error();
    return addHeapObject(ret);
  };
  imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) {
    const ret = getObject(arg1).stack;
    const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
    const len1 = WASM_VECTOR_LEN;
    getInt32Memory0()[arg0 / 4 + 1] = len1;
    getInt32Memory0()[arg0 / 4 + 0] = ptr1;
  };
  imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) {
    let deferred0_0;
    let deferred0_1;
    try {
      deferred0_0 = arg0;
      deferred0_1 = arg1;
      console.error(getStringFromWasm0(arg0, arg1));
    } finally {
      wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
    }
  };
  imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
    const ret = debugString(getObject(arg1));
    const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
    const len1 = WASM_VECTOR_LEN;
    getInt32Memory0()[arg0 / 4 + 1] = len1;
    getInt32Memory0()[arg0 / 4 + 0] = ptr1;
  };
  imports.wbg.__wbindgen_throw = function(arg0, arg1) {
    throw new Error(getStringFromWasm0(arg0, arg1));
  };
  return imports;
}
function __wbg_init_memory(imports, maybe_memory) {
}
function __wbg_finalize_init(instance, module) {
  wasm = instance.exports;
  __wbg_init.__wbindgen_wasm_module = module;
  cachedInt32Memory0 = null;
  cachedUint32Memory0 = null;
  cachedUint8Memory0 = null;
  return wasm;
}
async function __wbg_init(input) {
  if (wasm !== void 0)
    return wasm;
  if (typeof input === "undefined") {
    input = new URL("wasmjieba-web_bg.wasm");
  }
  const imports = __wbg_get_imports();
  if (typeof input === "string" || typeof Request === "function" && input instanceof Request || typeof URL === "function" && input instanceof URL) {
    input = fetch(input);
  }
  __wbg_init_memory(imports);
  const { instance, module } = await __wbg_load(await input, imports);
  return __wbg_finalize_init(instance, module);
}
console.log("participle worker loaded");
function segmentation(text) {
  return cutForSearch(text, false);
}
var log = (...args) => console.log("participle worker:", ...args);
var sleep = (ms = 16) => new Promise((resolve) => setTimeout(resolve, ms));
var isTextMessage = (message) => {
  if (!message)
    return false;
  if (!message.type)
    return false;
  if (message.type !== 1)
    return false;
  if (!message.content)
    return false;
  if (typeof message.content === "string") {
    if (message.content?.trim() === "")
      return false;
  }
  return true;
};
async function getIDBVersion(name) {
  const dbs = await indexedDB.databases();
  const db = dbs.find((db2) => db2.name === name);
  if (db) {
    return db.version || 0;
  }
  return 0;
}
function hasUndefined(...args) {
  return args.find((it) => it === void 0);
}
function getDBName(params, type = "participle") {
  const { ak, env, userId } = params;
  if (type === "main")
    return `${ak}/${env}/${userId}`;
  return `${ak}/${env}/${userId}/participle`;
}
var partciple = null;
var Partciple = class _Partciple {
  constructor(params) {
    this.searchModel = void 0;
    this.mainDB = void 0;
    this.dbVersion = 1;
    this.partcipleSequence = 0;
    this.isRunning = false;
    this.isInit = false;
    const { ak, env, userId } = params;
    if (hasUndefined(ak, env, userId)) {
      throw new Error("ak, env, userId is required");
    }
    this.params = params;
  }
  static {
    this.wasmPath = "";
  }
  async openParticipleDB() {
    const searchModel = new SearchModel();
    await searchModel.init(this.params);
    this.searchModel = searchModel;
  }
  getMainDBMessages(start, end) {
    const transaction = this.mainDB.transaction(["message"], "readonly");
    const store = transaction.objectStore("message");
    const index = store.index("sequence");
    const request = index.getAll(IDBKeyRange.bound(start, end));
    return new Promise((resolve, reject) => {
      request.onsuccess = (event) => {
        const data = event.target.result ?? [];
        const inChunkLast = data[data.length - 1];
        const result = data.filter((item) => {
          return isTextMessage(item);
        }).map((item) => {
          try {
            if (typeof item.content === "object") {
              return item;
            }
            const content = JSON.parse(item.content);
            return {
              ...item,
              content
            };
          } catch (error) {
            return void 0;
          }
        }).filter((item) => item !== void 0);
        resolve({ result, inChunkLastSequnce: inChunkLast?.sequence });
      };
      request.onerror = (event) => {
        reject(event);
      };
    });
  }
  async openMainDB() {
    const dbName = getDBName(this.params, "main");
    const dbVersion = await getIDBVersion(dbName);
    return new Promise((resolve, reject) => {
      const dbRequest = indexedDB.open(dbName, dbVersion);
      dbRequest.onerror = function(event) {
        console.error("participle worker openDB error:", event);
        reject(event);
      };
      dbRequest.onsuccess = () => {
        this.mainDB = dbRequest.result;
        resolve("");
      };
    });
  }
  async getTextMaxSequence() {
    const transaction = this.mainDB.transaction(["message"], "readonly");
    const store = transaction.objectStore("message");
    const index = store.index("sequence");
    const request = index.openCursor(null, "prev");
    return new Promise((resolve, reject) => {
      request.onsuccess = (event) => {
        const cursor = event.target.result;
        if (cursor) {
          const data = cursor.value;
          if (isTextMessage(data)) {
            resolve(data.sequence);
          } else {
            cursor.continue();
          }
        } else {
          resolve(0);
        }
      };
      request.onerror = (event) => {
        reject(event);
      };
    });
  }
  async isDone() {
    const currentParticipleSequence = await this.searchModel.getCacheParticipleSequence();
    const maxMessageSequence = await this.getTextMaxSequence();
    log("isDone", currentParticipleSequence >= maxMessageSequence);
    return currentParticipleSequence >= maxMessageSequence;
  }
  async run() {
    const startSeq = await this.searchModel.getCacheParticipleSequence() + 1;
    const endSeq = startSeq + 100;
    log("startSeq", startSeq);
    const { result: messages, inChunkLastSequnce } = await this.getMainDBMessages(startSeq, endSeq);
    for (let i = 0; i < messages.length; i++) {
      const item = messages[i];
      if (i === 0) {
        await this.searchModel.removeByseq(item.sequence);
      }
      if (item.content.text && typeof item.content.text === "string") {
        const _data = segmentation(item.content.text);
        for (let j = 0; j < _data.length; j++) {
          const value = _data[j];
          if (value.trim() === "") {
            continue;
          }
          try {
            await this.searchModel.addWord(
              {
                seq: item.sequence,
                words: value,
                mid: item.mid
              },
              j === _data.length - 1
            );
          } catch (error) {
            console.error("participle worker putWord error:", error);
          }
        }
        await sleep();
      }
    }
    await this.searchModel.setCacheParticipleSequence(inChunkLastSequnce);
  }
  async start() {
    if (this.isRunning) {
      return;
    }
    this.isRunning = true;
    if (!this.isInit) {
      await __wbg_init(_Partciple.wasmPath);
      this.isInit = true;
    }
    if (!this.searchModel) {
      await this.openParticipleDB();
    }
    if (!this.mainDB) {
      await this.openMainDB();
    }
    while (true) {
      const done = await this.isDone();
      if (done) {
        break;
      }
      await this.run();
    }
    this.isRunning = false;
  }
};
addEventListener("message", (event) => {
  const { type, payload } = event.data;
  try {
    log("onMessage", event.data);
    switch (type) {
      case "setWasmPath":
        Partciple.wasmPath = payload;
        break;
      case "init":
        partciple = new Partciple(payload);
        break;
      case "start":
        partciple.start();
        break;
      default:
    }
  } catch (error) {
    console.error("in participle worker:", error);
  }
});
