import {
  castOrDefaultValue,
  getStyleForPlatform,
  capitalise,
  applyStringTransformation,
  getOpacityFromHexColor,
  castIfDefined,
} from "../";

jest.mock("react-native", () => {
  const ReactNative = jest.requireActual("react-native");
  const RNMock = jest.genMockFromModule("react-native");
  const { Platform } = ReactNative;
  Platform.OS = "ios";

  // @ts-ignore
  return { ...RNMock, Platform };
});

describe("utils", () => {
  describe("castOrDefaultValue", () => {
    const mapper = jest.fn();
    const defaultValue = "lotus";

    it("applies mapper function to the value if not nil", () => {
      const testVal = "mclaren";
      castOrDefaultValue(mapper, defaultValue)(testVal);
      expect(mapper).toBeCalledWith(testVal);
    });

    it("returns default value if passed data is null, undefined or empty", () => {
      const partiallyApplied = castOrDefaultValue(mapper, defaultValue);

      expect(partiallyApplied(undefined)).toBe(defaultValue);
      expect(partiallyApplied(null)).toBe(defaultValue);
      expect(partiallyApplied([])).toBe(defaultValue);
      expect(partiallyApplied({})).toBe(defaultValue);
      expect(partiallyApplied("")).toBe(defaultValue);
    });
  });

  describe("castIfDefined", () => {
    it("should return identity if nil or undefined", () => {
      const mapper = jest.fn();
      const withNull = castIfDefined(mapper)(null);
      const withUndefined = castIfDefined(mapper)(undefined);

      expect(withUndefined).toEqual(undefined);
      expect(withNull).toEqual(null);
      expect(mapper).not.toBeCalled();
    });

    it("should pass value to the mapper if value isn't null or undefined", () => {
      const mapper = jest.fn();
      const testValue = "testValue";
      castIfDefined(mapper)(testValue);

      expect(mapper).toBeCalledWith(testValue);
    });
  });

  describe("getStyleForPlatform", () => {
    it("returns configuration value for correct platform", () => {
      const value = "test";

      const configuration = {
        test_ios_key: value,
      };

      const currentValue = getStyleForPlatform(configuration, ["test", "key"]);
      expect(currentValue).toBe(value);
    });
  });

  describe("capitalise", () => {
    it("capitalises passed text", () => {
      expect(capitalise("test")).toEqual("Test");
    });
  });

  describe("applyStringTransformation", () => {
    it("applies correct method on passed value", () => {
      const def = applyStringTransformation("test", "default");
      const upp = applyStringTransformation("test", "uppercase");
      const low = applyStringTransformation("TEST", "lowercase");
      const cap = applyStringTransformation("test", "capitalise");
      expect(def).toEqual("test");
      expect(upp).toEqual("TEST");
      expect(low).toEqual("test");
      expect(cap).toEqual("Test");
    });
  });

  describe("getOpacityFromHexColor", () => {
    it("correctly translates hex alpha to decimal", () => {
      const tenPercent = getOpacityFromHexColor("rgba(0, 0, 0, 0.10)");
      const zeroPercent = getOpacityFromHexColor("rgba(0, 0, 0, 0)");
      const hundredPercent = getOpacityFromHexColor("rgba(0, 0, 0, 1)");
      expect(tenPercent).toEqual(0.1);
      expect(zeroPercent).toEqual(0);
      expect(hundredPercent).toEqual(1);
    });

    it("can handles different alpha channel formats", () => {
      expect(getOpacityFromHexColor("rgba(0, 0, 0, 0.10)")).toEqual(0.1);
      expect(getOpacityFromHexColor("rgba(0, 0, 0, 0.11)")).toEqual(0.11);
      expect(getOpacityFromHexColor("rgba(0, 0, 0, .10)")).toEqual(0.1);
      expect(getOpacityFromHexColor("rgba(0, 0, 0, .11)")).toEqual(0.11);
      expect(getOpacityFromHexColor("rgba(0, 0, 0, 1.00)")).toEqual(1);
      expect(getOpacityFromHexColor("rgba(0, 0, 0, 0.00)")).toEqual(0);
    });
  });
});
