import * as Locale from "./locale";
import { firstValueFrom, of } from "rxjs";
import { Eno } from "./models/Eno";
import * as Send from "./send";
import { EnoFactory } from "./EnoFactory";
import { IEnSrvOptions } from "./IEnSrvOptions";
import { Batch } from "./models/types";
import { evalFormula, IFormulaOptions } from "./formula";

const testEnSrvOptions: IEnSrvOptions = {
  enSrvUrl: "http://example.com",
  namespace: "myNameSpace",
};

describe("formula", () => {
  let getLangsSpy: jasmine.Spy;

  beforeEach(() => {
    getLangsSpy = spyOn(Locale, "getLangs").and.returnValue(
      of(["fr-fr", "en-us"])
    );
  });

  it("should eval a formula", async () => {
    let formulaOpEno: Eno;

    spyOn(Send, "send").and.callFake((batch: Batch) => {
      formulaOpEno = batch[0];
      const responseEnoFactory = new EnoFactory("response/formula");
      responseEnoFactory.setSecurity("security/policy/everyone");
      responseEnoFactory.setField("response/formula:op", [formulaOpEno.tip]);
      responseEnoFactory.setField("response/formula:result", [
        "result1",
        "result2",
      ]);
      const responseEno = responseEnoFactory.makeEno();
      return of([responseEno]);
    });

    const formulaOptions: IFormulaOptions = {
      context: "my-context-tip",
      contextBranch: "my-context-branch-tip",
      vars: { key1: ["val1a", "val1b"] },
    };

    const results = await firstValueFrom(
      evalFormula("SOME_FORMULA_STRING()", testEnSrvOptions, formulaOptions)
    );

    expect(getLangsSpy).toHaveBeenCalledWith(testEnSrvOptions, undefined);
    expect(results).toEqual(["result1", "result2"]);

    expect(formulaOpEno.getType()).toBe("op/formula");
    expect(formulaOpEno.getFieldValues("op/formula:lang")).toEqual([
      "fr-fr",
      "en-us",
    ]);
    expect(formulaOpEno.getFieldValues("op/formula:context")).toEqual([
      "my-context-tip",
    ]);
    expect(formulaOpEno.getFieldValues("op/formula:context-branch")).toEqual([
      "my-context-branch-tip",
    ]);
    expect(formulaOpEno.getFieldValues("op/formula:vars")).toEqual([
      '{"key1":["val1a","val1b"]}',
    ]);
  });

  it("should eval a formula with lang", async () => {
    let formulaOpEno: Eno;

    spyOn(Send, "send").and.callFake((batch: Batch) => {
      formulaOpEno = batch[0];
      const responseEnoFactory = new EnoFactory("response/formula");
      responseEnoFactory.setSecurity("security/policy/everyone");
      responseEnoFactory.setField("response/formula:op", [formulaOpEno.tip]);
      responseEnoFactory.setField("response/formula:result", [
        "result1",
        "result2",
      ]);
      const responseEno = responseEnoFactory.makeEno();
      return of([responseEno]);
    });

    const formulaOptions: IFormulaOptions = {
      context: "my-context-tip",
      contextBranch: "my-context-branch-tip",
      vars: { key1: ["val1a", "val1b"] },
      lang: ["fr-fr", "es-es"],
    };

    const results = await firstValueFrom(
      evalFormula("SOME_FORMULA_STRING()", testEnSrvOptions, formulaOptions)
    );

    expect(getLangsSpy).toHaveBeenCalledWith(testEnSrvOptions, [
      "fr-fr",
      "es-es",
    ]);
    expect(results).toEqual(["result1", "result2"]);

    expect(formulaOpEno.getType()).toBe("op/formula");
    expect(formulaOpEno.getFieldValues("op/formula:lang")).toEqual([
      "fr-fr",
      "en-us",
    ]);
    expect(formulaOpEno.getFieldValues("op/formula:context")).toEqual([
      "my-context-tip",
    ]);
    expect(formulaOpEno.getFieldValues("op/formula:context-branch")).toEqual([
      "my-context-branch-tip",
    ]);
    expect(formulaOpEno.getFieldValues("op/formula:vars")).toEqual([
      '{"key1":["val1a","val1b"]}',
    ]);
  });
});
