import { Injectable } from '@angular/core';
import {
  AngularFirestore,
  AngularFirestoreCollection
} from '@angular/fire/firestore';
import * as firebase from 'firebase';
import { take } from 'rxjs/operators';
import { Address, AddressList } from './services/address';
import { CenterData } from './services/center';
import { SubjectService } from './subject.service';

@Injectable({
  providedIn: 'root'
})
export class AddressService {
  addressList: AddressList[] = [];
  nearestList: AddressList[] = [];
  defaultAdd: AddressList;
  custAddress: AddressList;
  centerLoc: CenterData;
  addressState: number;
  constructor(public afs: AngularFirestore, public subject: SubjectService) {
    this.addressState = 0;
    this.subject.getUserData().subscribe(userData => {
      if (userData) {
        console.log('address reinitialized');
        const userDatas = JSON.parse(userData);
        this.addList(userDatas.uid);
      }
    });
  }

  public async addList(userId: string) {
    const This = this;
    const state = true;
    const orderRef: AngularFirestoreCollection<any> = this.afs.collection(
      'address',
      ref => ref.where('status', '==', state).where('uid', '==', userId)
    );
    orderRef.valueChanges().subscribe(value => {
      this.addressList = [];
      const res = value;
      if (res.length > 0) {
        res.forEach(item => {
          // console.log(item);
          const address: AddressList = {
            address: item.address,
            addressType: item.addressType,
            latLng: item.latLng,
            defaultVal: item.defaultVal,
            building: item.building,
            landmark: item.landmark,
            addressId: item.addressId,
            nearest: false
          };
          this.addressList.push(address);
        });
        console.log(this.addressList);
      } else {
        // alert('No Orders Found');
      }
    });
  }

  public async defaultAddress(userId: string) {
    await new Promise(resolve => {
      const This = this;
      const state = true;
      const orderRef: AngularFirestoreCollection<any> = this.afs.collection(
        'address',
        ref => ref.where('status', '==', state).where('uid', '==', userId).where('defaultVal', '==', 1)
      );
      orderRef.valueChanges().subscribe(value => {
        const res = value;
        if (res.length > 0) {
          const item = res[0];
          // console.log(item);
          const address: AddressList = {
            address: item.address,
            addressType: item.addressType,
            latLng: item.latLng,
            defaultVal: item.defaultVal,
            building: item.building,
            landmark: item.landmark,
            addressId: item.addressId,
            nearest: false
          };
          this.defaultAdd = address;
          resolve(this.defaultAdd);
          console.log(this.defaultAdd);
        } else {
          // alert('No Orders Found');
        }
      });
    });
  }

  addressCreate(data: Address) {
    console.log(data);
    this.afs
      .collection('address')
      .add({})
      .then(docRef => {
        data.addressId = docRef.id;
        this.afs
          .collection('address')
          .doc(data.addressId)
          .set(data)
          .then(() => {
            this.setDefaultAddress(data.addressId, data.uid);
            // console.log('Address created Successfully');
          });
      });
  }


  changeAddress(data: Address, orderId) {
    console.log(data);
    this.afs
      .collection('orders').doc(orderId).update({ deliveryAddress: data });
  }

  async setDefaultAddress(addId: string, userId: string) {
    return await new Promise(resolve => {
      this.afs
        .collection('address', ref => ref.where('uid', '==', userId))
        .get()
        .forEach(item => {
          return item.docs.map(m => {
            return this.afs.doc(`address/${m.id}`).update({ defaultVal: 0 });
          });
        });
      setTimeout(() => {
        console.log(addId);
        this.afs
          .collection('address')
          .doc(addId)
          .update({ defaultVal: 1 })
          .then(() => {
            this.subject.setAddressStateData(true);
            resolve(true);
            console.log('Address updated Successfully');
          });
      }, 1000);
    });
  }

  deleteAddress(addId: string) {
    this.afs
      .collection('address')
      .doc(addId)
      .delete();
  }

  public async getNearBy(centerId, userId, distance) {


    // latitude, longitude, distance, userId
    console.log(centerId, userId, distance);
    this.custAddress = undefined;
    if (centerId) {
      this.afs.collection('centers').doc(centerId).ref.get().then((doc) => {
        if (doc.exists) {
          console.log('Document data:', doc.data());
          const center = doc.data();
          const This = this;
          const state = true;

          this.centerLoc = {
            cId: center.cId,
            centerImg: center.centerImg,
            centerName: center.centerName,
            description: center.description,
            featured: center.featured,
            latLng: center.latLng,
            location: center.location,
            status: center.status
          };

          const latitude = center.latLng.latitude;
          const longitude = center.latLng.longitude;

          const lat = 0.0144927536231884;
          const lon = 0.0181818181818182;

          console.log(latitude + ' - ' + lat + ' * ' + distance);

          const lowerLat = latitude - lat * distance;
          const lowerLon = longitude - lon * distance;

          const greaterLat = latitude + lat * distance;
          const greaterLon = longitude + lon * distance;

          console.log(lowerLat, lowerLon, greaterLat, greaterLon);

          const lesserGeopoint = new firebase.firestore.GeoPoint(lowerLat, lowerLon);
          const greaterGeopoint = new firebase.firestore.GeoPoint(
            greaterLat,
            greaterLon
          );
          const addressRef: AngularFirestoreCollection<any> = this.afs.collection(
            'address',
            ref =>
              ref
                .where('latLng', '>', lesserGeopoint)
                .where('latLng', '<', greaterGeopoint)
                .where('status', '==', state)
                .where('uid', '==', userId)
          );
          addressRef.valueChanges().subscribe(value => {
            this.nearestList = [];
            const res = value;
            if (res.length > 0) {
              res.forEach(item => {
                // console.log(item);
                const address: AddressList = {
                  address: item.address,
                  addressType: item.addressType,
                  latLng: item.latLng,
                  defaultVal: item.defaultVal,
                  building: item.building,
                  landmark: item.landmark,
                  addressId: item.addressId,
                  nearest: true
                };
                this.nearestList.push(address);
              });
              this.setAddress();
              console.log(this.nearestList);
            } else {
              // alert('No Orders Found');
            }

            if (this.addressList.length > 0) {
              this.addressList.forEach((address) => {
                address.nearest = false;
              });
              if (this.nearestList.length > 0) {
                this.addressList.forEach((address) => {
                  const index = this.nearestList.findIndex(x => x.addressId === address.addressId);
                  if (index >= 0) {
                    address.nearest = true;
                  }
                });
              }
              console.log(this.addressList);
            }




            this.addressList = this.addressList.sort((a: any, b: any) => {
              return b.nearest - a.nearest;
            });

            console.log(this.addressList);

          });
        } else {
          console.log('No such document!');
        }
      });
    }
  }

  setAddress() {
    this.custAddress = undefined;
    console.log(this.nearestList);
    if (this.nearestList.length > 0) {
      this.custAddress = this.nearestList.find(
        x => x.defaultVal === 1
      );
      /* if (!address) {
        address = this.nearestList[0];
      }
      this.custAddress = address; */
    }
  }
}
