import DatetimeAttributeModel from "../DatetimeAttributeModel";
import { ATTRIBUTE_WIDTH } from "../../../constants";

describe("datetimeAttributeModel", () => {
  it("should be able to create an empty DatetimeAttribute object", () => {
    const attribute = new DatetimeAttributeModel({}, { type: "datetime" });

    expect(attribute).toBeInstanceOf(DatetimeAttributeModel);

    expect(attribute.type).toBe("datetime");
    expect(attribute.format).toBe("yyyy-MM-dd'T'HH:mm:ss");
    expect(attribute.getInputValue()).toBe("");
    expect(attribute.inputvalue).toBe("");
    expect(attribute.readonlyvalue).toBe("");

    attribute.addConstraints();
    expect(attribute.constraintCollection).toHaveLength(1);
  });

  it("should be able to update", () => {
    const attribute = new DatetimeAttributeModel(
      {},
      {
        type: "datetime",
        format: "dd-MM-yyyy HH:mm",
      },
    );

    attribute.update("18-08-2016 13:45");
    expect(attribute.getInputValue()).toBe("18-08-2016 13:45");
    expect(attribute.getInitialInputValue("2016-08-18T13:45:23")).toBe(
      "18-08-2016 13:45",
    );

    expect(attribute.readonlyvalue).toBe("18-08-2016 13:45");

    attribute.update(null);
    expect(attribute.getInputValue()).toBe("");

    attribute.update("");
    expect(attribute.value).toBeNull();

    attribute.update("aaaa");
    expect(attribute.value).toBe("Invalid Date");
  });

  it("should be able to handle min and max date in only date format and renders in format", () => {
    const attribute = new DatetimeAttributeModel(
      {},
      {
        type: "datetime",
        format: "dd-MM-yyyy HH:mm",
        mindate: "2010-10-01T00:00:00",
        maxdate: "2010-10-31T23:59:59",
      },
    );

    attribute.update("18-08-2016 13:45");

    expect(attribute.isValid).toBe(false);
    expect(attribute.formatValue(attribute.mindate)).toBe("01-10-2010 00:00");
    expect(attribute.formatValue(attribute.maxdate)).toBe("31-10-2010 23:59");
  });

  it("should return AttributeWidth for dates", () => {
    const attribute = new DatetimeAttributeModel(
      {},
      {
        type: "date",
      },
    );
    expect(attribute.readonlyWidth).toBe(ATTRIBUTE_WIDTH.SMALL);
  });

  it("should return AttributeWidth for times", () => {
    const attribute = new DatetimeAttributeModel(
      {},
      {
        type: "time",
      },
    );
    expect(attribute.readonlyWidth).toBe(ATTRIBUTE_WIDTH.SMALL);
  });

  it("should return AttributeWidth for datetime", () => {
    const attribute = new DatetimeAttributeModel(
      {},
      {
        type: "datetime",
      },
    );
    expect(attribute.readonlyWidth).toBe(ATTRIBUTE_WIDTH.MEDIUM);
  });

  it("can validate datetime with datetime format", () => {
    const datetimeFormat = new DatetimeAttributeModel(
      {},
      {
        type: "datetime",
        format: "dd-MM-yyyy HH:mm",
      },
    );

    expect(datetimeFormat.validate("19-10-2010 1:45")).toBe(true);
    expect(datetimeFormat.validate("19-10-2010 13:45")).toBe(true);

    expect(datetimeFormat.validate("19-10-2010")).toBe(false);
    expect(datetimeFormat.validate("13:45")).toBe(false);
    expect(datetimeFormat.validate("19-10-2010 1:45 am")).toBe(false);
  });

  it("can validate datetime with only date format", () => {
    const dateFormat = new DatetimeAttributeModel(
      {},
      {
        type: "datetime",
        format: "dd-MM-yyyy",
      },
    );

    expect(dateFormat.validate("19-10-2010")).toBe(true);

    expect(dateFormat.validate("19-10-2010 1:45")).toBe(false);
    expect(dateFormat.validate("13:45")).toBe(false);
    expect(dateFormat.validate("19-10-2010 1:45 am")).toBe(false);
  });

  it("can validate datetime with datetime am/pm format", () => {
    const datetimeAmPmFormat = new DatetimeAttributeModel(
      {},
      {
        type: "datetime",
        format: "dd-MM-yyyy hh:mm a",
      },
    );

    expect(datetimeAmPmFormat.validate("19-10-2010 1:45 am")).toBe(true);
    expect(datetimeAmPmFormat.validate("19-10-2010 1:45 pm")).toBe(true);

    expect(datetimeAmPmFormat.validate("19-10-2010 1:45")).toBe(false);
    expect(datetimeAmPmFormat.validate("19-10-2010 13:45")).toBe(false);
  });

  it("can handle old datetime format with ms", () => {
    const attribute = new DatetimeAttributeModel(
      { value: "2031-12-21T17:41:21.000" },
      {
        type: "datetime",
        format: "dd-MM-yyyy HH:mm",
      },
    );

    expect(attribute.readonlyvalue).toBe("21-12-2031 17:41");
  });

  it("can handle custom format", () => {
    const attribute = new DatetimeAttributeModel(
      { value: "2031-12-21T17:41:21" },
      {
        type: "datetime",
        format: "dd-MM-yyyy HH:mm xxx",
      },
    );
    expect(attribute.readonlyvalue).toBe("21-12-2031 17:41 +01:00");

    const attribute2 = new DatetimeAttributeModel(
      { value: "2031-12-21T17:41:21" },
      {
        type: "datetime",
        format: "dd-MM-yyyy HH:mm Z",
      },
    );
    expect(attribute2.readonlyvalue).toBe("21-12-2031 17:41 +01");

    const attribute3 = new DatetimeAttributeModel(
      { value: "2031-12-21T17:41:21" },
      {
        type: "datetime",
        format: "EEE MMM dd, yyyy h:mma ZZ",
      },
    );
    expect(attribute3.readonlyvalue).toBe("Sun Dec 21, 2031 5:41PM +0100");
  });

  it("returns date part of formatlabel as placeholder if attribute has date and time", () => {
    const attribute = new DatetimeAttributeModel(
      {},
      {
        type: "datetime",
        format: "dd-MM-yyyy HH:mm",
        formatlabel: "dd-MM-yyyy HH:mm",
      },
    );

    expect(attribute.placeholder).toBe("dd-MM-yyyy");
  });

  it("does NOT contain offset in formdata property", () => {
    const attribute = new DatetimeAttributeModel(
      { key: "datetime", value: "2031-12-21T17:41:21" },
      { type: "datetime" },
    );

    expect(attribute.formdata).toEqual({ datetime: "2031-12-21T17:41:21" });
  });
});
