import API from './../API';

const ENDPOINT = "http://360-dev.pavie.info";
const URL_OK = ENDPOINT + "/api/search";
const TILES_OK = ENDPOINT + "/api/map/{z}/{x}/{y}.mvt";
const THIRD_PARTY_URL = "http://my.custom.api/points/to/stac/search";

describe('constructor', () => {
  it('works with valid endpoint', () => {
    const api = new API(URL_OK);
    expect(api._endpoint).toBe(URL_OK);
  });

  it('works with relative path', () => {
    const api = new API("/api/search");
    expect(api._endpoint).toBe("http://localhost/api/search");
  });

  it('fails if endpoint is invalid', () => {
    expect(() => new API("not an url")).toThrow("endpoint parameter is not a valid URL");
  });
});

describe('getPicturesAroundCoordinatesUrl', () => {
  it('works with valid coordinates', () => {
    const api = new API(URL_OK);
    expect(api.getPicturesAroundCoordinatesUrl(48.7, -1.25)).toBe(`${URL_OK}?bbox=[-1.2505,48.6995,-1.2495,48.7005]`);
  });

  it('fails if coordinates are invalid', () => {
    const api = new API(URL_OK);
    expect(() => api.getPicturesAroundCoordinatesUrl()).toThrow("lat and lon parameters should be valid numbers");
  });
});

describe('getPictureMetadataUrl', () => {
  it('works with valid ID', () => {
    const api = new API(URL_OK);
    expect(api.getPictureMetadataUrl("whatever-id")).toBe(`${URL_OK}?ids=["whatever-id"]`);
  });

  it('fails if picId is invalid', () => {
    const api = new API(URL_OK);
    expect(() => api.getPictureMetadataUrl()).toThrow("picId should be a valid picture unique identifier");
  });
});

describe('getPicturesTilesUrl', () => {
  it('works if URL is set in options', () => {
    const url = "http://360-dev.pavie.info/custom/route/{z}/{x}/{y}";
    const api = new API(URL_OK, url);
    expect(api.getPicturesTilesUrl()).toBe(url);
  });

  it('works if endpoint is Geovisio', () => {
    const api = new API(URL_OK);
    expect(api.getPicturesTilesUrl()).toBe(TILES_OK);
  });

  it('fails with custom endpoint and no pictures URL set', () => {
    const api = new API(THIRD_PARTY_URL);
    expect(() => api.getPicturesTilesUrl()).toThrow("Pictures vector tiles URL is unknown");
  });
});

describe('getPictureThumbnailUrl', () => {
  it('works with a geovisio instance', () => {
    const api = new API(URL_OK);
    return api.getPictureThumbnailUrl("picId").then(url => {
      expect(url).toBe(ENDPOINT + "/api/pictures/picId/thumb.jpg");
    });
  });

  it('works with a third-party STAC API', () => {
    // Mock API search
    const thumbUrl = "http://my.custom.api/pic/thumb.jpg";
    global.fetch = jest.fn(() => Promise.resolve({
      json: () => Promise.resolve({
        features: [ {
          "assets": {
            "thumb": {
              "href": thumbUrl,
              "roles": ["thumbnail"],
              "type": "image/jpeg"
            }
          }
        }]
      })
    }));

    const api = new API(THIRD_PARTY_URL);
    return api.getPictureThumbnailUrl("picId").then(url => {
      expect(url).toBe(thumbUrl);
    });
  });

  it('works with a third-party STAC API without thumbnail', () => {
    // Mock API search
    global.fetch = jest.fn(() => Promise.resolve({
      json: () => Promise.resolve({
        features: [ {
          "assets": {}
        }]
      })
    }));

    const api = new API(THIRD_PARTY_URL);
    return api.getPictureThumbnailUrl("picId").then(url => {
      expect(url).toBe(undefined);
    });
  });
});

describe('getPictureThumbnailForSequence', () => {
  it('works with an existing sequence', () => {
    const resPicId = "cbfc3add-8173-4464-98c8-de2a43c6a50f";
    const thumbUrl = "http://my.custom.api/pic/thumb.jpg";
    // Mock API search
    global.fetch = jest.fn(() => Promise.resolve({
      json: () => Promise.resolve({
        features: [ {
          "id": resPicId,
          "assets": {
            "thumb": {
              "href": thumbUrl,
              "roles": ["thumbnail"],
              "type": "image/jpeg"
            }
          }
        }]
      })
    }));

    const api = new API(THIRD_PARTY_URL);
    return api.getPictureThumbnailForSequence("208b981a-262e-4966-97b6-98ee0ceb8df0").then(picMeta => {
      expect(picMeta.id).toBe(resPicId);
      expect(Object.values(picMeta.assets).find(a => a.roles.includes("thumbnail")).href).toBe(thumbUrl);
    });
  });

  it('works with no results', () => {
    // Mock API search
    global.fetch = jest.fn(() => Promise.resolve({
      json: () => Promise.resolve({
        features: []
      })
    }));

    const api = new API(THIRD_PARTY_URL);
    return api.getPictureThumbnailForSequence("208b981a-262e-4966-97b6-98ee0ceb8df0").then(picMeta => {
      expect(picMeta).toBe(null);
    });
  });
});

describe('isGeoVisioInstance', () => {
  it('works with Geovisio', () => {
    const api = new API(URL_OK);
    expect(api.isGeoVisioEndpoint()).toBeTruthy();
  });

  it('works with any other STAC API instance', () => {
    const api = new API(THIRD_PARTY_URL);
    expect(api.isGeoVisioEndpoint()).toBeFalsy();
  });
});

describe('getGeoVisioRoot', () => {
  it('works with simple URL', () => {
    const api = new API(URL_OK);
    expect(api.getGeoVisioRoot()).toBe(ENDPOINT);
  });

  it('works with URL and added parameters', () => {
    const api = new API(URL_OK+"?bla=bla");
    expect(api.getGeoVisioRoot()).toBe(ENDPOINT);
  });

  it('fails on not-Geovisio API', () => {
    const api = new API(THIRD_PARTY_URL);
    expect(() => api.getGeoVisioRoot()).toThrow("Can't get root endpoint on a third-party STAC API");
  });
});

describe('isValidHttpUrl', () => {
  it('works with valid endpoint', () => {
    expect(API.isValidHttpUrl(URL_OK)).toBeTruthy();
  });

  it('fails if endpoint is invalid', () => {
    expect(API.isValidHttpUrl("not an url")).toBeFalsy();
  });
});
