window.indexedDB = window.indexedDB ||
	window.mozIndexedDB ||
	window.webkitIndexedDB ||
	window.msIndexedDB;

window.IDBTransaction = window.IDBTransaction ||
	window.webkitIDBTransaction ||
	window.msIDBTransaction;

window.IDBKeyRange = window.IDBKeyRange ||
	window.webkitIDBKeyRange ||
	window.msIDBKeyRange;

/**
 * 获取数据库操作对象
 * @param {*} dbName 数据名称
 * @param {*} objectStoreDefines 表定义
 * @param {*} version 版本号，整数，举例：1
 */
function IndexDbFactory(dbName, objectStoreDefines, version) {

	this.dbName = dbName;

	this.objectStoreDefines = objectStoreDefines;

	this.version = version;

	this.db = null;

	this.open = function (successCallback, errorCallback) {
		let _self = this;

		var request = window.indexedDB.open(this.dbName, version);


		request.onsuccess = function (e) {
			_self.db = request.result;
			console.log('数据库 %s 打开成功', _self.dbName);
			successCallback();
		};


		request.onupgradeneeded = function (e) {
			_self.db = e.target.result;
			var names = _self.db.objectStoreNames;
			for (let index = 0; index < _self.objectStoreDefines.length; index++) {
				let objectStoreName = _self.objectStoreDefines[index].name;
				if (names.contains(objectStoreName)) {
					// 如果 ObjectStore 已经存在，那么先删除数据
					_self.db.deleteObjectStore(objectStoreName);
				}
				let objectStoreDefinesOption = _self.objectStoreDefines[index].defineOption;
				var objectStore = _self.db.createObjectStore(
					objectStoreName,
					objectStoreDefinesOption
				);
				let indexDefines = _self.objectStoreDefines[index].indexDefineList;
				if (indexDefines != null) {
					for (let index1 = 0; index1 < indexDefines.length; index1++) {
						let indexDefine = indexDefines[index1];
						objectStore.createIndex(indexDefine.indexName, indexDefine.keyPath, indexDefine.objectParameters);
					}
				}
			}
			console.log('数据库 %s 升级成功', _self.dbName);
			successCallback();
		};

		request.onerror = function (e) {
			console.error('数据库 %s 打开异常，异常编号 %s，异常信息。', _self.dbName, e.target.code, e);
			errorCallback();
		};
	};

	this.close = function () {
		this.db.close();
		this.db = null;
		console.log('数据库 %s 已经关闭', this.dbName);
	}


	this.getObjectStore = function (mode, objectStoreName) {
		let _self = this;
		mode = mode || 'readonly';
		var txn = _self.db.transaction([_self.objectStoreName], mode);
		return store;
	};

	/**
	 * 保存/修改数据
	 * put 方法重复添加数据会覆盖原有数据
	 * @param {*} objectStoreName 表名
	 * @param {*} data 待保存的数据
	 * @param {*} successCallback 操作成功 callback
	 * @param {*} errorCallback 操作失败 callback
	 */
	this.put = function (objectStoreName, data, successCallback, errorCallback) {
		let _self = this;
		if (_self.db == null) {
			errorCallback('数据库打开失败。');
			return;
		}
		var transaction = _self.db.transaction([objectStoreName], 'readwrite');
		var store = transaction.objectStore(objectStoreName);
		// 修改数据，可以使用put, 添加数据也可以用put, put方法重复添加数据会覆盖原有数据
		var request = store.put(data);
		request.onsuccess = successCallback;
		request.onerror = errorCallback;
	};

	/**
	 * 查询objectStore中所有的数据
	 * @param {*} objectStoreName 
	 * @param {*} successCallback 
	 * @param {*} errorCallback 
	 * @returns 
	 */
	this.getAll = function (objectStoreName, successCallback, errorCallback) {
		let _self = this;
		if (_self.db == null) {
			errorCallback('数据库打开失败');
			return;
		}

		var transaction = _self.db.transaction([objectStoreName], 'readonly');
		var store = transaction.objectStore(objectStoreName);
		var cursor = store.openCursor();
		var datas = [];

		cursor.onsuccess = function (e) {
			var result = e.target.result;
			if (result && result !== null) {
				datas.push(result.value);
				result.continue();
			} else {
				successCallback(datas);
			}
		};
		cursor.onerror = errorCallback;
	};


	/**
	 * 根据索引名称查询objectStore中所有的数据
	 * @param {*} objectStoreName 
	 * @param {*} successCallback 
	 * @param {*} errorCallback 
	 * @returns 
	 */
	this.getAllByIndexName = function (objectStoreName, indexName, keyRange, successCallback, errorCallback) {
		let _self = this;
		if (_self.db == null) {
			errorCallback('数据库打开失败');
			return;
		}

		var transaction = _self.db.transaction([objectStoreName], 'readonly');
		var store = transaction.objectStore(objectStoreName);
		var index = store.index(indexName);
		//打开游标，通过IDBKeyRange设置游标范围，这里设置为只获取age等于18的数据
		var cursor = index.openCursor(keyRange);
		var datas = [];
		cursor.onsuccess = function (e) {
			var result = e.target.result;
			if (result && result !== null) {
				datas.push(result.value);
				result.continue();
			} else {
				successCallback(datas);
			}
		};
		cursor.onerror = errorCallback;
	}

	this.get = function (objectStoreName, id, successCallback, errorCallback) {
		let _self = this;
		if (_self.db == null) {
			errorCallback('数据库打开失败');
			return;
		}

		var transaction = _self.db.transaction([objectStoreName], 'readonly');
		var store = transaction.objectStore(objectStoreName);

		var request = store.get(id);
		request.onsuccess = function (e) {
			successCallback(e.target.result);
		};
		request.onerror = errorCallback;
	};

	/**
	 * 删除一条数据
	 * @param {*} id 
	 * @param {*} successCallback 
	 * @param {*} errorCallback 
	 * @returns 
	 */
	this.deleteOne = function (objectStoreName, id, successCallback, errorCallback) {
		let _self = this;
		if (_self.db == null) {
			errorCallback('数据库打开失败');
			return;
		}
		var transaction = _self.db.transaction([objectStoreName], 'readwrite');
		var store = transaction.objectStore(objectStoreName);
		var request = store.delete(id);
		request.onsuccess = successCallback;
		request.onerror = errorCallback;
	};

	this.deleteAll = function (objectStoreName, callback) {
		let _self = this;
		if (_self.db == null) {
			errorCallback('数据库打开失败');
			return;
		}
		var transaction = _self.db.transaction([objectStoreName], 'readwrite');
		var store = transaction.objectStore(objectStoreName);
		var request = store.clear();
		request.onsuccess = callback;
	}
}