/*
 * Copyright (C) 2019-2021 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {TestBed} from '@angular/core/testing';
import {MapModule} from './map.module';
import {Geolocation, Geoposition} from '@ionic-native/geolocation/ngx';
import {defer} from 'rxjs';
import {HttpClientModule} from '@angular/common/http';
import {StorageModule} from '../storage/storage.module';
import {MapPosition, PositionService} from './position.service';
import {Diagnostic} from '@ionic-native/diagnostic/ngx';
import {ConfigProvider} from '../config/config.provider';
import {
  LoggerConfig,
  LoggerModule,
  NGXLogger,
  NGXMapperService,
} from 'ngx-logger';

/**
 * For faking a promise resolve
 */
function fakeAsyncResponse<T>(data: T) {
  return defer(() => Promise.resolve(data));
}

describe('PositionService', () => {
  let geolocation: Geolocation;
  let positionService: PositionService;

  const sampleMapPosition: MapPosition = {
    heading: 123,
    latitude: 34.12,
    longitude: 12.34,
  };
  const samplePosition: Geoposition = {
    coords: {
      ...sampleMapPosition,
      accuracy: 1,
      altitude: 123,
      altitudeAccuracy: 1,
      speed: 1,
    },
    timestamp: 1_565_275_805_901,
  } as Geoposition;

  beforeEach(async () => {
    const configProvider = {
      getValue: () => {
        Promise.resolve();
      },
    };

    TestBed.configureTestingModule({
      imports: [MapModule, HttpClientModule, StorageModule, LoggerModule],
      providers: [
        Geolocation,
        Diagnostic,
        LoggerConfig,
        NGXLogger,
        NGXMapperService,
        {
          provider: ConfigProvider,
          useValue: configProvider,
        },
      ],
    });
    positionService = TestBed.inject(PositionService);
    geolocation = TestBed.inject(Geolocation);
    spyOn(geolocation, 'getCurrentPosition').and.returnValue(
      Promise.resolve(samplePosition),
    );

    spyOn(geolocation, 'watchPosition').and.callFake(() => {
      return fakeAsyncResponse(samplePosition);
    });
  });

  it('should provide the current location of the device', async () => {
    expect(await positionService.getCurrentLocation()).toEqual(
      sampleMapPosition,
    );
  });

  it('should continuously provide (watch) location of the device', async () => {
    expect(
      positionService
        .watchCurrentLocation()
        .subscribe(result => expect(result).toEqual(sampleMapPosition)),
    );
  });
});
