﻿/**
 * Data caching for online and offline storage of query results, using user service to query data.
 * 
 * @license
 * Copyright (c) 2018-2020 Double P Software Piotr Pytlik. All rights reserved.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: Understand the data structure or at least major entities so that we can pre-load them in bulk when online or skip already present data?
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//import { api } from './api.js';
import { splash } from '/src/pwa/controls/pp-splash.js';

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
class Lookup {
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	private _id: string;
	private _t: string;
	private _data: any[] | null;
    private _idx: { [key: string]: any } | null;	//index;	// NOTE that most our keys are numeric, but Program uses 'CC' string

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// all elements have ID named 'id' + entity as well as a string label named 't' + entity
	constructor( public entity: string, public nest?: { entity: string, map: ( obj: any ) => any, t?: string }) {
		this._id = nest
			? "id" + nest.entity
			: "id" + entity;
		this._t = nest
			? nest.t
				? nest.t
				: "t" + nest.entity
			: "t" + entity;
		this._data = null;
		this._idx = null;	//data.then(l => this._init(l[entity], nest));
    }

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	init( sys: Sys ) {
		this._idx = {};
		const data = sys.data[this.entity];
		this._data = data;
		if( this.nest )	// https://stackoverflow.com/questions/10865025/merge-flatten-an-array-of-arrays-in-javascript
			this._data = [].concat( ...data.map( e => this.nest!.map( e ) ) );	// don't know how this.nest can be undefined? Using !.
		if( !this._data ) {
			console.error( "NO DATA for " + this.entity );
		}
		for( var el of this._data ) {
			this._idx[el[this._id]] = el;
		}
    }

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public get data() {
		return this._data;
	}

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// Returning a Promise of the element, not the element itself as it may not have loaded yet.
	public el( id: string | number ) {
		return this._idx ? this._idx[id] : null;
		//return this._idx![id];	// _init should have been called BEFORE this call so let's tell ts it's non-null with a !
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// Returning a Promise of the element text, not the text itself as it may not have loaded yet.
	public txt( id: string | number ) {
		const el = this.el( id );
		return el ? el[this._t] : id;	// TODO: how do we return DefaultSource if no id ?
    }

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
*/

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Sys {
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public data: { [key: string]: any[] } = {};

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public Config: { MapApiKey: string | null };

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public ready: Promise<any>;	// use it in Promise.all to ensure sys is ready before any other action is dispatched that may rely on it, see userActions._selectClientYear

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	constructor() {
		splash.auto = false;
		splash.setState( "Loading" );

		this.Config = { MapApiKey: null };

		// TODO: convert that to init() or load() so that we can force a reload any time
		splash.remove();	// remove the initial splash screen as soon as the system data has been fully loaded
		this.ready = Promise.resolve( null );
	}

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// use it as sys.whenReady( promise ).then().catch() to ensure sys and promise are ready before it resolves
	whenReady( promise: Promise<any> ) {
		return Promise.all( [promise, this.ready] )	// ensure sys is ready / resolved alongside api.field.fields before dispatch
			.then( values => values[0] );	// returns the result of promise, ignores the result of ready but ensures both are resolved
	}

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: we should NEVER call sys unless the api.system.lookups is resolved so the data is available, don't want Promises here!
export const sys = new Sys();
export default sys;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
