/** 网络数据编解码 */

export default () => {

	return new class {

		/**
		 * 将字符串编码为无符号8位整数数组
		 * @param {String} str
		 */
		strencode(str) {
			var byteArray = new Uint8Array(str.length * 3);
			var offset = 0;
			for (var i = 0; i < str.length; i++) {
				/** 字符的Unicode编码值 */
				var charCode = str.charCodeAt(i);
				var codes = null;

				// 如果编码值小于等于127
				if (charCode <= 0x7f) {
					codes = [charCode];
				}
				// 编码值>127且小于等于2047
				else if (charCode <= 0x7ff) {
					codes = [0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f)];
				}
				// 其他编码值
				else {
					codes = [0xe0 | (charCode >> 12), 0x80 | ((charCode & 0xfc0) >> 6), 0x80 | (charCode & 0x3f)];
				};

				for (var j = 0; j < codes.length; j++) {
					byteArray[offset] = codes[j];
					++offset;
				};
			};

			var _buffer = new Uint8Array(offset);
			this.copyArray(_buffer, 0, byteArray, 0, offset);

			return _buffer;
		};

		/**
		 * 将二进制数据解码为字符串
		 * @param {Uint8Array} buffer 
		 */
		strdecode(buffer) {
			/** 二进制数据 */
			var bytes = new Uint8Array(buffer);
			/** unicode编码的数组 */
			var array = [];
			/** 数据偏移量 */
			var offset = 0;
			/** 承载字符编码的临时变量 */
			var charCode = 0;
			/** 结束的位置 */
			var end = bytes.length;

			while (offset < end) {
				if (bytes[offset] < 128) {
					charCode = bytes[offset];
					offset += 1;
				} else if (bytes[offset] < 224) {
					charCode = ((bytes[offset] & 0x3f) << 6) + (bytes[offset + 1] & 0x3f);
					offset += 2;
				} else {
					charCode = ((bytes[offset] & 0x0f) << 12) + ((bytes[offset + 1] & 0x3f) << 6) + (bytes[offset + 2] & 0x3f);
					offset += 3;
				};

				array.push(charCode);
			};

			var str = '';
			for (var i = 0; i < array.length;) {
				str += String.fromCharCode.apply(null, array.slice(i, i + 10000));
				i += 10000;
			};

			return str;
		};

		/**
		 * 克隆字节数组
		 * @param {Array} dest 目标数组-需要复制数据到的目标数组
		 * @param {Number} doffset 目标数组偏移量
		 * @param {Array} src 源数组-源数据的数组
		 * @param {Number} soffset 源数组偏移量
		 * @param {Number} length 要复制的源数组数据长度
		 */
		copyArray(dest, doffset, src, soffset, length) {
			if ('function' === typeof src.copy) {
				// Buffer
				src.copy(dest, doffset, soffset, soffset + length);
			} else {
				// Uint8Array
				for (var index = 0; index < length; index++) {
					dest[doffset++] = src[soffset++];
				};
			};
		};
	};
}