/**
 * Created by rockyl on 2019-12-18.
 */

const version = 5;
const storeConfigs = [
	{name: 'project', key: 'id'},
	{name: 'mock', key: 'path'},
	{name: 'preview', key: 'id'},
	{name: 'packages', key: 'id'},
	{
		name: 'pack-history', key: 'id', autoIncrement: true, indices: [
			{name: 'pid', unique: false}
		]
	},
];

export default {
	open(databaseName = 'store') {
		return new Promise((resolve, reject) => {
			let request = window.indexedDB.open(databaseName, version);
			request.onerror = function (event) {
				reject(event.target.error);
			};
			request.onsuccess = (event) => {
				this.db = event.target.result;
				resolve(request.result);
			};
			request.onupgradeneeded = (event) => {
				this.db = event.target.result;
				this.createStore(storeConfigs);
			}
		})
	},

	createStore(stores) {
		for (let {name, key, autoIncrement, indices} of stores) {
			if (!this.db.objectStoreNames.contains(name)) {
				let store = this.db.createObjectStore(name, {keyPath: key || 'id', autoIncrement: !!autoIncrement});
				if (indices) {
					for (let {name, unique} of indices) {
						store.createIndex(name, name, {unique})
					}
				}
			}
		}
	},

	get(storeName, id) {
		return new Promise((resolve, reject) => {
			let request = this.db.transaction([storeName])
				.objectStore(storeName)
				.get(id);

			request.onerror = function (event) {
				reject(event.target.error);
			};

			request.onsuccess = function (event) {
				resolve(request.result);
			};
		})
	},

	getAll(storeName, id, index) {
		return new Promise((resolve, reject) => {
			let store = this.db.transaction([storeName]).objectStore(storeName);
			let request;
			if (index) {
				let indexStore = store.index(index);
				request = indexStore.getAll(id);
			} else {
				request = store.getAll();
			}

			request.onerror = function (event) {
				reject(event.target.error);
			};

			request.onsuccess = function (event) {
				resolve(request.result);
			};
		})
	},

	add(storeName, data) {
		return new Promise((resolve, reject) => {
			let request = this.db.transaction([storeName], 'readwrite')
				.objectStore(storeName)
				.add(data);

			request.onsuccess = function (event) {
				resolve();
			};

			request.onerror = function (event) {
				reject(event.target.error);
			}
		});
	},

	put(storeName, data) {
		return new Promise((resolve, reject) => {
			let request = this.db.transaction([storeName], 'readwrite')
				.objectStore(storeName)
				.put(data);

			request.onsuccess = function (event) {
				resolve();
			};

			request.onerror = function (event) {
				reject(event.target.error);
			}
		});
	},

	async set(storeName, data) {
		try {
			await this.add(storeName, data);
		} catch (e) {
			await this.put(storeName, data);
		}
	},

	remove(storeName, id) {
		return new Promise((resolve, reject) => {
			let request = this.db.transaction([storeName], 'readwrite')
				.objectStore(storeName)
				.delete(id);

			request.onsuccess = function (event) {
				resolve();
			};

			request.onerror = function (event) {
				reject(event.target.error);
			}
		});
	},

	clear(storeName) {
		return new Promise((resolve, reject) => {
			let request = this.db.transaction([storeName], 'readwrite')
				.objectStore(storeName)
				.clear();

			request.onsuccess = function (event) {
				resolve();
			};

			request.onerror = function (event) {
				reject(event.target.error);
			}
		});
	},
}