goog.provide('ol.test.source.TileImageSource');

describe('ol.source.TileImage', function() {
  function createSource(opt_proj, opt_tileGrid) {
    var proj = opt_proj || 'EPSG:3857';
    return new ol.source.TileImage({
      projection: proj,
      tileGrid: opt_tileGrid ||
          ol.tilegrid.createForProjection(proj, undefined, [2, 2]),
      tileUrlFunction: ol.TileUrlFunction.createFromTemplate(
          'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=')
    });
  }

  describe('#setTileGridForProjection', function() {
    it('uses the tilegrid for given projection', function() {
      var source = createSource();
      var tileGrid = ol.tilegrid.createForProjection('EPSG:4326', 3, [10, 20]);
      source.setTileGridForProjection('EPSG:4326', tileGrid);
      var retrieved = source.getTileGridForProjection(ol.proj.get('EPSG:4326'));
      expect(retrieved).to.be(tileGrid);
    });
  });

  describe('#getTileInternal', function() {
    var source, tile;

    beforeEach(function() {
      source = createSource();
      expect(source.getKeyParams()).to.be('');
      source.getTileInternal(0, 0, -1, 1, ol.proj.get('EPSG:3857'));
      expect(source.tileCache.getCount()).to.be(1);
      tile = source.tileCache.get(source.getKeyZXY(0, 0, -1));
    });

    it('gets the tile from the cache', function() {
      var returnedTile = source.getTileInternal(
          0, 0, -1, 1, ol.proj.get('EPSG:3857'));
      expect(returnedTile).to.be(tile);
    });

    describe('change a dynamic param', function() {

      describe('tile is not loaded', function() {
        it('returns a tile with no interim tile', function() {
          source.getKeyParams = function() {
            return 'key0';
          };
          var returnedTile = source.getTileInternal(
              0, 0, -1, 1, ol.proj.get('EPSG:3857'));
          expect(returnedTile).not.to.be(tile);
          expect(returnedTile.key).to.be('key0');
          expect(returnedTile.interimTile).to.be(null);
        });
      });

      describe('tile is loaded', function() {
        it('returns a tile with interim tile', function() {
          source.getKeyParams = function() {
            return 'key0';
          };
          tile.state = ol.TileState.LOADED;
          var returnedTile = source.getTileInternal(
              0, 0, -1, 1, ol.proj.get('EPSG:3857'));
          expect(returnedTile).not.to.be(tile);
          expect(returnedTile.key).to.be('key0');
          expect(returnedTile.interimTile).to.be(tile);
        });
      });

      describe('tile is not loaded but interim tile is', function() {
        it('returns a tile with interim tile', function() {
          var dynamicParamsKey, returnedTile;
          source.getKeyParams = function() {
            return dynamicParamsKey;
          };
          dynamicParamsKey = 'key0';
          tile.state = ol.TileState.LOADED;
          returnedTile = source.getTileInternal(
              0, 0, -1, 1, ol.proj.get('EPSG:3857'));
          dynamicParamsKey = 'key1';
          returnedTile = source.getTileInternal(
              0, 0, -1, 1, ol.proj.get('EPSG:3857'));
          expect(returnedTile).not.to.be(tile);
          expect(returnedTile.key).to.be('key1');
          expect(returnedTile.interimTile).to.be(tile);
        });
      });

    });

  });

  describe('#getTile', function() {
    it('does not do reprojection for identity', function() {
      var source3857 = createSource('EPSG:3857');
      var tile3857 = source3857.getTile(0, 0, -1, 1, ol.proj.get('EPSG:3857'));
      expect(tile3857).to.be.a(ol.ImageTile);
      expect(tile3857).not.to.be.a(ol.reproj.Tile);

      var projXXX = new ol.proj.Projection({
        code: 'XXX',
        units: 'degrees'
      });
      var sourceXXX = createSource(projXXX);
      var tileXXX = sourceXXX.getTile(0, 0, -1, 1, projXXX);
      expect(tileXXX).to.be.a(ol.ImageTile);
      expect(tileXXX).not.to.be.a(ol.reproj.Tile);
    });

    beforeEach(function() {
      proj4.defs('4326_noextentnounits', '+proj=longlat +datum=WGS84 +no_defs');
    });

    afterEach(function() {
      delete proj4.defs['4326_noextentnounits'];
    });

    it('can handle source projection without extent and units', function(done) {
      var source = createSource('4326_noextentnounits', ol.tilegrid.createXYZ({
        extent: [-180, -90, 180, 90],
        tileSize: [2, 2]
      }));
      var tile = source.getTile(0, 0, -1, 1, ol.proj.get('EPSG:3857'));
      expect(tile).to.be.a(ol.reproj.Tile);

      ol.events.listen(tile, 'change', function() {
        if (tile.getState() == ol.TileState.LOADED) {
          done();
        }
      });
      tile.load();
    });

    it('can handle target projection without extent and units', function(done) {
      var proj = ol.proj.get('4326_noextentnounits');
      var source = createSource();
      source.setTileGridForProjection(proj,
          ol.tilegrid.createXYZ({
            extent: [-180, -90, 180, 90],
            tileSize: [2, 2]
          }));
      var tile = source.getTile(0, 0, -1, 1, proj);
      expect(tile).to.be.a(ol.reproj.Tile);

      ol.events.listen(tile, 'change', function() {
        if (tile.getState() == ol.TileState.LOADED) {
          done();
        }
      });
      tile.load();
    });
  });
});

goog.require('ol.ImageTile');
goog.require('ol.Tile');
goog.require('ol.TileState');
goog.require('ol.TileUrlFunction');
goog.require('ol.events');
goog.require('ol.proj');
goog.require('ol.proj.Projection');
goog.require('ol.reproj.Tile');
goog.require('ol.source.TileImage');
