import { Jimp, mkJGD, getTestDir } from "@jimp/test-utils";
import configure from "@jimp/custom";
import types from "@jimp/types";
import expect from "@storybook/expect";

import color from "../src";
import { expectToBeJGD } from "@jimp/test-utils/src";

const jimp = configure({ types: [types], plugins: [color] }, Jimp);

describe("Convolution", function () {
  this.timeout(15000);

  const imgs = [
    jimp.read(
      mkJGD(
        "22222222",
        "22222222",
        "22888822",
        "22888822",
        "22888822",
        "22888822",
        "22222222",
        "22222222"
      )
    ),
    jimp.read(
      mkJGD(
        "88222222",
        "88222222",
        "22222222",
        "22222222",
        "22222222",
        "22222222",
        "22222222",
        "22222222"
      )
    ),
  ];

  let imgMid;
  let imgTopLeft; // stores the Jimp instances of the JGD images above.

  before((done) => {
    Promise.all(imgs)
      .then((imgs) => {
        imgMid = imgs[0];
        imgTopLeft = imgs[1];
        done();
      })
      .catch(done);
  });

  const sharpM = [
    [-1, -1, 0],
    [-1, 1, 1],
    [0, 1, 1],
  ];

  const blurM = [
    [1 / 9, 1 / 9, 1 / 9],
    [1 / 9, 1 / 9, 1 / 9],
    [1 / 9, 1 / 9, 1 / 9],
  ];

  it("3x3 sharp matrix on EDGE_EXTEND", (done) => {
    expectToBeJGD(
      imgMid.clone().convolution(sharpM).getJGDSync(),
      mkJGD(
        "22222222",
        "28EEE822",
        "2EFFF802",
        "2EF88002",
        "2EF88002",
        "28800002",
        "22000002",
        "22222222"
      )
    );

    expectToBeJGD(
      imgTopLeft.clone().convolution(sharpM).getJGDSync(),
      mkJGD(
        "80022222",
        "00022222",
        "00022222",
        "22222222",
        "22222222",
        "22222222",
        "22222222",
        "22222222"
      )
    );
    done();
  });

  it("3x3 sharp matrix on EDGE_WRAP", (done) => {
    expectToBeJGD(
      imgMid.clone().convolution(sharpM, jimp.EDGE_WRAP).getJGDSync(),
      mkJGD(
        "22222222",
        "28EEE822",
        "2EFFF802",
        "2EF88002",
        "2EF88002",
        "28800002",
        "22000002",
        "22222222"
      )
    );

    expectToBeJGD(
      imgTopLeft.clone().convolution(sharpM, jimp.EDGE_WRAP).getJGDSync(),
      mkJGD(
        "F802222E",
        "80022228",
        "00022222",
        "22222222",
        "22222222",
        "22222222",
        "22222222",
        "E8222228"
      )
    );
    done();
  });

  it("3x3 sharp matrix on EDGE_CROP", (done) => {
    expectToBeJGD(
      imgMid.clone().convolution(sharpM, jimp.EDGE_CROP).getJGDSync(),
      mkJGD(
        "86666662",
        "68EEE820",
        "6EFFF800",
        "6EF88000",
        "6EF88000",
        "68800000",
        "62000000",
        "20000000"
      )
    );

    expectToBeJGD(
      imgTopLeft.clone().convolution(sharpM, jimp.EDGE_CROP).getJGDSync(),
      mkJGD(
        "FC066662",
        "C0022220",
        "00022220",
        "62222220",
        "62222220",
        "62222220",
        "62222220",
        "20000000"
      )
    );
    done();
  });

  it("3x3 box blur matrix using convolute", async () => {
    const expectedImg = await jimp.read(
      getTestDir(__dirname) + "/images/tiles-blurred.png"
    );

    const image = await jimp.read(getTestDir(__dirname) + "/images/tiles.jpg");

    expect(image.convolute(blurM).bitmap.data).toEqual(expectedImg.bitmap.data);
  });

  it("new pixel value is greater than 255", async () => {
    const expectedImg = await jimp.read(
      getTestDir(__dirname) + "/images/qr-convoluted.png"
    );
    const image = await jimp.read(getTestDir(__dirname) + "/images/qr.jpg");

    expect(
      image.convolution([
        [0, 0, 0, 0, 0],
        [0, 1, 1, 1, 0],
        [0, 1, 0, 1, 0],
        [0, 1, 1, 1, 0],
        [0, 0, 0, 0, 0],
      ]).bitmap.data
    ).toEqual(expectedImg.bitmap.data);
  });
});
