import { expect } from "chai";
import { documentContext, inline } from "./testUtils";
import { limitScopeByIndentation } from "./limitScopeByIndentation";

describe("postprocess", () => {
  describe("limitScopeByIndentation", () => {
    it("should drop multiline completions, when the suffix have meaningful chars in the current line.", () => {
      const context = {
        ...documentContext`
        let error = new Error("Something went wrong");
        console.log(║message);
        `,
        language: "javascript",
      };
      const completion = inline`
                    ├message);
        throw error;┤
      `;
      expect(limitScopeByIndentation(context)(completion)).to.be.null;
    });

    it("should allow singleline completions, when the suffix have meaningful chars in the current line.", () => {
      const context = {
        ...documentContext`
        let error = new Error("Something went wrong");
        console.log(║message);
        `,
        language: "javascript",
      };
      const completion = inline`
                    ├error, ┤
      `;
      expect(limitScopeByIndentation(context)(completion)).to.eq(completion);
    });

    it("should allow multiline completions, when the suffix only have special chars that will be replaced in the current line, such as `)]}`.", () => {
      const context = {
        ...documentContext`
        function findMax(arr) {║}
        `,
        language: "javascript",
      };
      const completion = inline`
                               ├
          let max = arr[0];
          for (let i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
              max = arr[i];
            }
          }
          return max;
        }┤
      `;
      expect(limitScopeByIndentation(context)(completion)).to.eq(completion);
    });

    it("should limit scope at sentence end, when completion is continuing uncompleted sentence in the prefix.", () => {
      const context = {
        ...documentContext`
        let a =║
        `,
        language: "javascript",
      };
      const completion = inline`
               ├ 1;
        let b = 2;┤
      `;
      const expected = inline`
               ├ 1;┤
      `;
      expect(limitScopeByIndentation(context)(completion)).to.eq(expected);
    });

    it("should limit scope at sentence end, when completion is continuing uncompleted sentence in the prefix.", () => {
      const context = {
        ...documentContext`
        function safeParse(json) {
          try {
            console.log║
          } catch (error) {
            console.error(error);
            return null;
          }
        }
        `,
        language: "javascript",
      };
      const completion = inline`
                        ├("Parsing", { json });
            return JSON.parse(json);
          } catch (e) {
            return null;
          }
        }┤
      `;
      const expected = inline`
                        ├("Parsing", { json });┤
      `;
      expect(limitScopeByIndentation(context)(completion)).to.eq(expected);
    });

    it("should limit scope at next indent level, including closing line, when completion is continuing uncompleted sentence in the prefix, and starting a new indent level in next line.", () => {
      const context = {
        ...documentContext`
        function findMax(arr) {║}
        `,
        language: "javascript",
      };
      const completion = inline`
                               ├
          let max = arr[0];
          for (let i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
              max = arr[i];
            }
          }
          return max;
        }
        console.log(findMax([1, 2, 3, 4, 5]));┤
      `;
      const expected = inline`
                               ├
          let max = arr[0];
          for (let i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
              max = arr[i];
            }
          }
          return max;
        }┤
      `;
      expect(limitScopeByIndentation(context)(completion)).to.eq(expected);
    });

    it("should limit scope at next indent level, including closing line, when completion is continuing uncompleted sentence in the prefix, and starting a new indent level in next line.", () => {
      const context = {
        ...documentContext`
        function findMax(arr) {
          let max = arr[0];
          for║
        }
        `,
        language: "javascript",
      };
      const completion = inline`
             ├ (let i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
              max = arr[i];
            }
          }
          return max;
        }
        console.log(findMax([1, 2, 3, 4, 5]));┤
      `;
      const expected = inline`
             ├ (let i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
              max = arr[i];
            }
          }┤
        ┴┴
      `;
      expect(limitScopeByIndentation(context)(completion)).to.eq(expected);
    });

    it("should limit scope at current indent level, exclude closing line, when completion starts new sentences at same indent level.", () => {
      const context = {
        ...documentContext`
        function findMax(arr) {
          let max = arr[0];║
        }
        `,
        language: "javascript",
      };
      const completion = inline`
                           ├
          for (let i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
              max = arr[i];
            }
          }
          return max;
        }┤
      `;
      const expected = inline`
                           ├
          for (let i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
              max = arr[i];
            }
          }
          return max;┤
        ┴┴
      `;
      expect(limitScopeByIndentation(context)(completion)).to.eq(expected);
    });

    it("should allow only one level closing bracket", () => {
      const context = {
        ...documentContext`
        function safeParse(json) {
          try {
            return JSON.parse(json);
          } catch (e) {
            return null;║
        `,
        language: "javascript",
      };
      const completion = inline`
                        ├
          }
        }┤
      `;
      const expected = inline`
                        ├
          }┤
        ┴┴
      `;
      expect(limitScopeByIndentation(context)(completion)).to.eq(expected);
    });

    it("should allow level closing bracket at current line, it looks same as starts new sentences", () => {
      const context = {
        ...documentContext`
        function helloworld() {
          console.log("hello");
          ║
        `,
        language: "javascript",
      };
      const completion = inline`
          ├}┤
      `;
      expect(limitScopeByIndentation(context)(completion)).to.be.eq(completion);
    });

    it("should not allow level closing bracket, when the suffix lines have same indent level", () => {
      const context = {
        ...documentContext`
        function helloworld() {
          console.log("hello");║
          console.log("world");
        }
        `,
        language: "javascript",
      };
      const completion = inline`
                               ├
        }┤
      `;
      const expected = inline`
                               ├┤`;
      expect(limitScopeByIndentation(context)(completion)).to.be.eq(expected);
    });

    it("should use indent level of previous line, when current line is empty.", () => {
      const context = {
        ...documentContext`
        function safeParse(json) {
          try {
            ║
          }
        }
        `,
        language: "javascript",
      };
      const completion = inline`
            ├return JSON.parse(json);
          } catch (e) {
            return null;
          }
        }┤
      `;
      const expected = inline`
            ├return JSON.parse(json);
          } catch (e) {
            return null;
          }┤
        ┴┴
      `;
      expect(limitScopeByIndentation(context)(completion)).to.eq(expected);
    });
  });
});
