import { Http , Response } from '@angular/http' ; import { esIndex } from './consts' ; import { Injectable , Inject } from "@angular/core" ; import * as firebase from 'firebase' ; import { } from 'firebase' ; import { Observable } from "rxjs/Observable" ; import { FormGroup } from '@angular/forms' ; import { Subject } from 'rxjs/Subject' ; import { Subscription } from 'rxjs/Rx' ; /**
 * Service that realize logic with connecting to firebase realtime database and authentication.
 * Components user doesn't directly calls connector method. He calls them from [DAL] https *
 * Querying to `Firebase Realtime Database` are executed with [Firebase Flashlight] https .
 * If you want to create you own connector you must adopt it to `ElasticSearch flashlight` output.
  @ Injectable ( ) export class FirebaseConnector { /**
     * User visited router
     */ private sfVisitedRoutes ; /**
     * User performed clicks
     */ private sfUserClicks ; private basketHistory$ : Subject < any > = new Subject ( ) ; private basketHistorySubscription$ : Subscription ; private orderSubject : Subject < any > = new Subject ( ) ; private database = firebase . database ( ) ; private auth = firebase . auth ( ) ; constructor ( private http ) { } /**
     * Connect [Session-flow] https to databese.
     *
     *  param { SessionFlow } sessionFlow param { string } deviceId param { string } sessionId connectSessionFlowToDB ( sessionFlow , deviceId , sessionId ) { this . sfVisitedRoutes = this . database . ref ( '/session-flows/' + deviceId + '/' + sessionId + '/visitedRoutes' ) ; this . sfUserClicks = this . database . ref ( '/session-flows/' + deviceId + '/' + sessionId + '/userClicks' ) ; this . listenSfObject ( sessionFlow ) ; } param { SessionFlow } sf private listenSfObject ( sf ) { sf . visitedRoute . subscribe ( ( value ) => { this . sfVisitedRoutes . push ( value . getStringObject ( ) ) ; } ) ; sf . click . asObservable ( ) . subscribe ( ( value ) => { this . sfUserClicks . push ( value . getStringObject ( ) ) ; } ) ; } returns getFirebase ( ) { return firebase ; } ; returns getFirebaseDB ( ) { return this . database ; } returns getAuth ( ) { return this . auth ; } param { string } email param { string } password returns [firebase.Promise] https containing non-null [firebase.User] https register ( email , password ) { return this . auth . createUserWithEmailAndPassword ( email , password ) ; } param registerForm registerUser ( registerForm ) { let email = registerForm . email ; let password = registerForm . password ; delete registerForm . password ; let userId = this . guid ( ) ; registerForm [ "registerTime" ] = Date . now ( ) ; return Observable . create ( observer => { this . register ( email , password ) . then ( authData => { let uid = authData . uid ; registerForm . uid = uid ; this . database . ref ( 'user/' + userId ) . set ( registerForm ) . then ( data => { this . loginEmail ( email , password ) . subscribe ( data => { observer . next ( data ) ; observer . complete ( ) ; } , error => { observer . error ( error ) ; } ) ; } ) ; } ) . catch ( error => { observer . error ( error ) ; } ) ; } ) ; } returns private guid ( ) { function s4 ( ) { return Math . floor ( ( 1 + Math . random ( ) ) * 0x10000 ) . toString ( 16 ) . substring ( 1 ) ; } return s4 ( ) + s4 ( ) + '-' + s4 ( ) + '-' + s4 ( ) + '-' + s4 ( ) + '-' + s4 ( ) + s4 ( ) + s4 ( ) ; } param { string } email param { string } password returns { Observable } Observable containing non-null [firebase.User] https loginEmail ( email , password ) { return Observable . create ( observer => { this . auth . signInWithEmailAndPassword ( email , password ) . then ( data => { observer . next ( data ) ; observer . complete ( ) ; } ) . catch ( error => { observer . error ( error ) ; observer . complete ( ) ; } ) ; } ) ; } param { string } uid returns [firebase.database.Reference] https getUserData ( uid ) { let queryObj = { query : { match : { "uid" : uid } } } ; return this . requestData ( esIndex , 'user' , queryObj ) ; } /**
     * Logout user from firebase
     */ logout ( ) { this . auth . signOut ( ) ; } param { string } deviceId checkOldSessionFlow ( deviceId ) { if ( localStorage . getItem ( "oldSessionFlow" ) ) { let oldSessionFlow = JSON . parse ( localStorage . getItem ( "oldSessionFlow" ) ) ; let sessionId = oldSessionFlow . sessionId ; delete oldSessionFlow . sessionId ; this . database . ref ( '/session-flows/' + deviceId + '/' + sessionId ) . set ( oldSessionFlow ) ; } } param { string } userId returns { Observable } getBasketContent ( userId ) { return Observable . create ( observer => { this . database . ref ( ) . child ( '/basket/' + userId ) . on ( 'value' , data => { observer . next ( data ) ; } ) ; } ) ; } /**
     * Will be realized in next versions
     */ getComparison ( id ) { return this . database . ref ( ) . child ( 'comparison/' + id ) . once ( 'value' ) ; } param { string } userId initializeBasketHistory ( userId ) { if ( this . basketHistorySubscription$ ) { this . basketHistorySubscription$ . unsubscribe ( ) ; } this . basketHistorySubscription$ = this . basketHistory$ . subscribe ( data => { this . database . ref ( '/basket-history/' + userId ) . push ( data ) ; } ) ; } returns { Subject } getBasketHistorySubject ( ) { return this . basketHistory$ ; } param { string } userId returns { Observable } getBasketHistoryById ( userId ) { return Observable . fromPromise ( this . database . ref ( ) . child ( '/basket-history/' + userId ) . once ( 'value' ) as Promise < any > ) ; } param id param newBasket returns { Observable } setNewBasket ( id , newBasket ) { return Observable . create ( observer => { this . database . ref ( ) . child ( 'basket/' + id ) . set ( newBasket ) . then ( data => { observer . next ( data ) ; observer . complete ( ) ; } ) ; } ) ; } /**
     * Will be realized in next versions
     */ addProductToComparison ( id , product ) { return this . database . ref ( ) . child ( 'comparison/' + id ) . push ( product ) ; } /**
     * Will be realized in next versions
     */ removeProductFromComparison ( id , idInComparison ) { return this . database . ref ( ) . child ( 'comparison/' + id + '/' + idInComparison ) . remove ( ) ; } /**
     * Gets data hits from firebase using [flashlight] https lib for ElasticSearch
     *
     *  param { string } index param { string } type param { Object } body returns { Observable } requestData ( index , type , body ) { const key = this . database . ref ( 'search/request' ) . push ( { index , type , body } ) . key ; return Observable . fromPromise ( this . database . ref ( `search/response/${ key }/hits/hits` ) . once ( 'child_added' ) as Promise < any > ) ; } /**
     * Gets full data from firebase using [flashlight] https lib for ElasticSearch
     *
     *  param { string } index param { string } type param { Object } body returns { Observable } requestFullData ( index , type , body ) { const key = this . database . ref ( 'search/request' ) . push ( { index , type , body } ) . key ; return Observable . fromPromise ( this . database . ref ( `search/response/${ key }/hits` ) . once ( 'child_added' ) as Promise < any > ) ; } /**
     * Gets total item of data from firebase using [flashlight] https lib for ElasticSearch
     *
     *  param { string } index param { string } type param { Object } body returns { Observable } requestItemsTotal ( index , type , body ) { const key = this . database . ref ( 'search/request' ) . push ( { index , type , body } ) . key ; console . log ( key ) ; return Observable . create ( observer => { const ref = this . database . ref ( `search/response/${ key }/hits/total` ) ; let promise = new Promise ( ( resolve , reject ) => { ref . on ( 'value' , ( data ) => { if ( data . val ( ) !== null ) { resolve ( data ) ; } } ) ; } ) ; promise . then ( data => { ref . off ( 'value' ) ; observer . next ( data ) ; observer . complete ( ) ; } ) ; } ) ; } param { Object } product addProduct ( product ) { this . database . ref ( 'product/' ) . push ( product ) ; } returns getVisitedRoutes ( ) { return this . sfVisitedRoutes ; } returns getUserClicks ( ) { return this . sfUserClicks ; } param { FormGroup } generalCategoryForm addGeneralCategory ( generalCategoryForm ) { this . database . ref ( 'general-category' ) . push ( generalCategoryForm . value ) ; } param { FormGroup } categoryForm addCategory ( categoryForm ) { this . database . ref ( 'category/' ) . push ( categoryForm . value ) ; } param { FormGroup } attributeForm param { string } categoryId addAttribute ( attributeForm , categoryId ) { this . database . ref ( 'attributes/' ) . push ( attributeForm . value ) . then ( ref => { this . database . ref ( ) . child ( 'category/' + categoryId + '/attrs' ) . once ( 'value' ) . then ( data => { if ( data . val ( ) ) { console . log ( data ) ; if ( data . val ( ) [ 0 ] == '1234' && data . val ( ) [ 1 ] == '1234' ) { let attrs = [ '1234' ] ; attrs . push ( ref [ 'key' ] ) ; console . log ( attrs ) ; this . database . ref ( ) . child ( 'category/' + categoryId + '/attrs' ) . set ( attrs ) ; } else { let attrs = [ ] . concat ( ... data . val ( ) ) ; console . log ( attrs ) ; attrs . push ( ref [ 'key' ] ) ; console . log ( attrs ) ; this . database . ref ( ) . child ( 'category/' + categoryId + '/attrs' ) . set ( attrs ) ; } } } ) ; } ) ; } param { FormGroup } tagForm param { string } categoryId addTag ( tagForm , categoryId ) { this . database . ref ( 'tags/' ) . push ( tagForm . value ) . then ( ref => { this . database . ref ( ) . child ( 'category/' + categoryId + '/tags' ) . once ( 'value' ) . then ( data => { if ( data . val ( ) ) { console . log ( data ) ; if ( data . val ( ) [ 0 ] == '1234' && data . val ( ) [ 1 ] == '1234' ) { let tags = [ '1234' ] ; tags . push ( ref [ 'key' ] ) ; console . log ( tags ) ; this . database . ref ( ) . child ( 'category/' + categoryId + '/tags' ) . set ( tags ) ; } else { let tags = [ ] . concat ( data . val ( ) ) ; tags . push ( ref [ 'key' ] ) ; console . log ( tags ) ; this . database . ref ( ) . child ( 'category/' + categoryId + '/tags' ) . set ( tags ) ; } } } ) ; } ) ; } param { Object } paymentData returns { Observable } saveOrder ( paymentData ) { return Observable . create ( observer => { this . database . ref ( 'orders' ) . push ( paymentData ) . then ( data => { observer . next ( data ) ; observer . complete ( ) ; } ) ; } ) ; } param { Object } data param { string } paymentMethod returns [firebase.database.ThenableReference] https addPaymentRequest ( data , paymentMethod ) { return this . database . ref ( 'payment-request' ) . push ( { data : data , payMethod : paymentMethod } ) ; } param { string } paymentKey returns { Observable } listenPaymentResponse ( paymentKey ) { return Observable . create ( observer => { this . database . ref ( 'payment-response/' + paymentKey ) . on ( 'value' , data => { if ( data . val ( ) ) { observer . next ( data ) ; } } ) ; } ) ; } param { string } email returns [firebase.Promise] https containing void
      resetPassword ( email ) { return this . auth . sendPasswordResetEmail ( email ) ; } param id returns { Observable } getOrderById ( id ) { return Observable . create ( observer => { this . database . ref ( 'orders/' + id ) . on ( 'value' , data => { if ( data . val ( ) ) { observer . next ( data . val ( ) ) ; } } ) ; } ) ; } returns { Observable } listenOrders ( ) { return Observable . create ( observer => { this . database . ref ( 'orders' ) . on ( 'child_added' , newOrder => { if ( newOrder . val ( ) ) { observer . next ( newOrder . val ( ) ) ; } } ) ; } ) ; } getOrderSubject ( ) { return this . orderSubject ; } getSeoText ( url , indexBlock ) { return Observable . create ( observer => { this . database . ref ( 'seo-text' ) . orderByChild ( 'url' ) . equalTo ( url ) . on ( 'value' , data => { if ( data . val ( ) && data . val ( ) !== null ) { Object . keys ( data . val ( ) ) . map ( key => { observer . next ( data . val ( ) [ key ] [ 'blocks' ] [ indexBlock ] ) ; } ) ; } else { observer . next ( null ) ; } } ) ; } ) ; } }