

var Tools = function(){

	var cuPrint = function(dom, options){
		var Print = function () {
		  if (!(this instanceof Print)) return new Print(dom, options);

		  this.options = this.extend({
			'noPrint': '.no-print'
		  }, options);

		  if ((typeof dom) === "string") {
			this.dom = document.querySelector(dom);
		  } else {
			this.isDOM(dom)
			this.dom = this.isDOM(dom) ? dom : dom.$el;
		  }

		  this.init();
		};
		Print.prototype = {
		  init: function () {
			var content = this.getStyle() + this.getHtml();
			this.writeIframe(content);
		  },
		  extend: function (obj, obj2) {
			for (var k in obj2) {
			  obj[k] = obj2[k];
			}
			return obj;
		  },

		  getStyle: function () {
			var str = "",
			  styles = document.querySelectorAll('style,link');
			for (var i = 0; i < styles.length; i++) {
			  str += styles[i].outerHTML;
			}
			str += "<style>" + (this.options.noPrint ? this.options.noPrint : '.no-print') + "{display:none;}</style>";

			return str;
		  },

		  getHtml: function () {
			var inputs = document.querySelectorAll('input');
			var textareas = document.querySelectorAll('textarea');
			var selects = document.querySelectorAll('select');

			for (var k = 0; k < inputs.length; k++) {
			  if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
				if (inputs[k].checked == true) {
				  inputs[k].setAttribute('checked', "checked")
				} else {
				  inputs[k].removeAttribute('checked')
				}
			  } else if (inputs[k].type == "text") {
				inputs[k].setAttribute('value', inputs[k].value)
			  } else {
				inputs[k].setAttribute('value', inputs[k].value)
			  }
			}

			for (var k2 = 0; k2 < textareas.length; k2++) {
			  if (textareas[k2].type == 'textarea') {
				textareas[k2].innerHTML = textareas[k2].value
			  }
			}

			for (var k3 = 0; k3 < selects.length; k3++) {
			  if (selects[k3].type == 'select-one') {
				var child = selects[k3].children;
				for (var i in child) {
				  if (child[i].tagName == 'OPTION') {
					if (child[i].selected == true) {
					  child[i].setAttribute('selected', "selected")
					} else {
					  child[i].removeAttribute('selected')
					}
				  }
				}
			  }
			}
			// 包裹要打印的元素
			// fix: https://github.com/xyl66/vuePlugs_printjs/issues/36
			let outerHTML = this.wrapperRefDom(this.dom).outerHTML
			return outerHTML;
		  },
		  // 向父级元素循环，包裹当前需要打印的元素
		  // 防止根级别开头的 css 选择器不生效
		  wrapperRefDom: function (refDom) {
			let prevDom = null
			let currDom = refDom
			// 判断当前元素是否在 body 中，不在文档中则直接返回该节点
			if (!this.isInBody(currDom)) return currDom

			while (currDom) {
			  if (prevDom) {
				let element = currDom.cloneNode(false)
				element.appendChild(prevDom)
				prevDom = element
			  } else {
				prevDom = currDom.cloneNode(true)
			  }

			  currDom = currDom.parentElement
			}

			return prevDom
		  },

		  writeIframe: function (content) {
			var w, doc, iframe = document.createElement('iframe'),
			  f = document.body.appendChild(iframe);
			iframe.id = "myIframe";
			//iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
			iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;');
			w = f.contentWindow || f.contentDocument;
			doc = f.contentDocument || f.contentWindow.document;
			doc.open();
			doc.write(content);
			doc.close();
			var _this = this
			iframe.onload = function(){
			  _this.toPrint(w);
			  setTimeout(function () {
				document.body.removeChild(iframe)
			  }, 100)
			}
		  },

		  toPrint: function (frameWindow) {
			try {
			  setTimeout(function () {
				frameWindow.focus();
				try {
				  if (!frameWindow.document.execCommand('print', false, null)) {
					frameWindow.print();
				  }
				} catch (e) {
				  frameWindow.print();
				}
				frameWindow.close();
			  }, 10);
			} catch (err) {
			  console.log('err', err);
			}
		  },
		  // 检查一个元素是否是 body 元素的后代元素且非 body 元素本身
		  isInBody: function (node) {
			return (node === document.body) ? false : document.body.contains(node);
		  },
		  isDOM: (typeof HTMLElement === 'object') ?
			function (obj) {
			  return obj instanceof HTMLElement;
			} :
			function (obj) {
			  return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
			}
		};
		Print();
	};

	var downloadFile = function(obj, name, suffix){
		var url = window.URL.createObjectURL(new Blob([obj]));
		var link = document.createElement('a');
		link.style.display = 'none';
		link.href = url;
		var fileName = name + '.' + suffix;
		link.setAttribute('download', fileName);
		document.body.appendChild(link);
		link.click();
		document.body.removeChild(link);
	};

	// 水波图表
	var waveMapChart = function(ctn, val, opts){
		opts = opts || {};
		var dpr = window.devicePixelRatio || qf.envir.dpr;
		var dpr = 2;
		var insetMargin = 3 * dpr;
		var devX = (insetMargin - 1) * dpr;	// 波浪起始和结束点偏移
		var textColor = opts.textColor || '#fff';
		var styleColor = opts.styleColor || '#2d99fc';
		var shadowColor = opts.shadowColor || opts.styleColor;

		let M = Math, Sin = M.sin, Cos = M.cos, Sqrt = M.sqrt, Pow = M.pow, PI = M.PI, Round = M.round;
		let lineWidth = 2, nowdata = 0, data = (val || 0) / 100; // 线宽
		let range = .3;							// 浪幅
		let nowrange = range;
		let waveupsp = 0.008;					// 水波上涨速度
		let sp = 0;								// 周期偏移量
		let xoffset = 8 * lineWidth;			// x 轴偏移量
		let sinLength = 1.8;						// sin 长度

		var Widget = function(ctn){
			var ctn = this.ctn = typeof element === "string" ? document.getElementById(ctn) : ctn;
			if(!ctn) return console.log('%c cuCharts Error Element is a invalid param! ', 'color:red');

			var self = this, setDpr = 1;
			self.dpr = dpr * setDpr;
			self.Cache = {};
			
			var canvas = this.canvas = document.createElement("canvas");
			canvas.style.cssText = 'position:absolute;height:100%;width:100%;';
			this.ctx = canvas.getContext("2d");
			ctn.appendChild(canvas);

			return this.init();
		}; Widget.prototype = {
			init: function(){
				// 圆动画初始参数
				let arcStack = [];				// 圆栈
				let bR = this.r - 2 * lineWidth;
				let soffset = -(PI / 2);		// 圆动画起始位置

				this.setModule();
				this.onresize();

				// 获取圆动画轨迹点集
				for (var i = soffset; i < soffset + 2 * PI; i += 1 / (8 * PI)) {
					arcStack.push([
						this.r + bR * Cos(i),
						this.r + bR * Sin(i)
					])
				};
				// 圆起始点
				let cStartPoint = arcStack.shift();
				this.ctx.strokeStyle = "#1c86d1";
				this.ctx.moveTo(cStartPoint[0], cStartPoint[1]);
				this.render();
				return this
			},
			setModule: function(){
				this.ctx.clearRect(0, 0, this.SumWidth, this.SumHeight);
				var canvas = this.canvas;
				var SumWidth = this.SumWidth = (this.ctn.clientWidth*this.dpr);
				var SumHeight = this.SumHeight = (this.ctn.clientHeight*this.dpr);
				this.width = canvas.width = SumWidth;
				this.height = canvas.height = SumHeight;

				canvas.style.cssText = 'position:absolute;top:0;left:0;height:'+(SumHeight/this.dpr)+'px;width:'+(SumWidth/this.dpr)+'px;user-select: none;-webkit-tap-highlight-color:rgba(0,0,0,0);padding:0;margin:0;border-width:0;box-sizing: border-box;';

				var r = this.r = SumWidth / 2;
				this.cR = r - 0 * dpr * lineWidth;
				this.axisLength = sinLength * r * lineWidth;	// Sin 图形长度
				this.unit = this.axisLength / 9;				// 波浪宽
				this.drawChart();
			},
			onresize: function(){
				qf.resize(() => {if(this.ctn.clientWidth){this.setModule();}});
			},
			drawChart: function(){
				//最外面淡黄色圈
				this.drawCircle();
				//灰色圆圈
				this.grayCircle();

				//橘黄色进度圈
				this.orangeCircle();

				//裁剪中间水圈
				this.clipCircle();
				
				// 阴影
				this.drwaInsetShadow();

				if (data >= 0.85) {
					if (nowrange > range / 4) {
						var t = range * 1.02;
						nowrange -= t;
					}
				} else if (data <= 0.3) {
					nowrange = 0.15
					/* if (nowrange < 0.01 * 1.5) {
						var t = 0.1 * 1.01;
						nowrange += t;
					} */
				} else {
					if (nowrange <= range) {
						var t = range * 1.01;
						nowrange += t;
					}
					if (nowrange >= range) {
						var t = range * 1.01;
						nowrange -= t;
					}
				}
				if ((data - nowdata) > 0) {
					nowdata += waveupsp;
				}else{
					nowdata = data;
				};
				sp += 0.07;

				// 开始水波动画
				this.drawSine();

				// 写字
				this.drawText();
			},
			drawWave: function(){
			},
			render: function(){
				if(!isNaN(this.ctn.clientWidth)){
					this.ctx.clearRect(0, 0, this.width, this.height);
					this.drawChart();
					this.requestFrame = requestAnimationFrame(this.render.bind(this))
				}else{
					this.clear();
					this.render = null;
					this.setModule = null;
				}
			},
			drawCircle: function(){
				var lineWidth = 1 * dpr;
				var mg = 0 * dpr - lineWidth;
				this.ctx.beginPath();
				this.ctx.lineWidth = lineWidth;
				this.ctx.strokeStyle = styleColor;
				this.ctx.arc(this.r, this.r, this.cR + mg, 0, 2 * Math.PI);
				this.ctx.stroke();
				this.ctx.restore();
			},
			grayCircle: function(){
				var lineWidth = 1 * dpr;
				var mg = insetMargin * dpr;
				this.ctx.beginPath();
				this.ctx.lineWidth = lineWidth;
				this.ctx.strokeStyle = '#eaeaea';
				this.ctx.arc(this.r, this.r, this.cR - mg, 0, 2 * Math.PI);
				this.ctx.stroke();
				this.ctx.restore();
				this.ctx.beginPath();
			},
			orangeCircle: function(){
				var mg = insetMargin * dpr;
				this.ctx.beginPath();
				this.ctx.strokeStyle = styleColor;
				//使用这个使圆环两端是圆弧形状
				this.ctx.lineCap = 'round';
				var startRadian = 0 * (Math.PI / 180.0) - (Math.PI / 2);
				var endtRadian = (nowdata * 360) * (Math.PI / 180.0) - (Math.PI / 2);
				this.ctx.arc(this.r, this.r, this.cR - mg, startRadian, endtRadian);
				this.ctx.stroke();
				this.ctx.save()
			},
			clipCircle: function(){
				this.ctx.beginPath();
				this.ctx.arc(this.r, this.r, this.cR-devX, 0, 2 * Math.PI, false);
				this.ctx.clip();
			},
			drawSine: function(){
				this.ctx.beginPath();
				this.ctx.save();
				var Stack = []; // 记录起始点和终点坐标
				
				// 波幅修正, 解决过高和过底的问题
				var a = 100 / 2 - nowdata.toFixed(4) * 100;		// 方向
				var b = (insetMargin+2) / 50;					// 基数
				var c = a * b;
				for (var i = xoffset; i <= xoffset + this.axisLength; i += 20 / this.axisLength) {
					var x = sp + (xoffset + i) / this.unit;
					var y = Sin(x) * nowrange;
					var dy = 2 * this.cR * (1 - nowdata) + (this.r - this.cR - c) - (this.unit * y);
					this.ctx.lineTo(i+devX, dy);
					Stack.push([i-devX, dy])
				};

				// 获取初始点和结束点
				var startP = Stack[0];
				var endP = Stack[Stack.length - 1];
				this.ctx.lineTo(xoffset + this.axisLength, this.width);
				this.ctx.lineTo(xoffset, this.width);
				this.ctx.lineTo(startP[0], startP[1]);
				this.ctx.fillStyle = styleColor;
				this.ctx.fill();
				this.ctx.restore();
			},
			drwaInsetShadow: function(){
				var mg = insetMargin * dpr;
				var r = this.r;
				var rgrd = this.ctx.createRadialGradient(r+mg, r+mg, 0, r, r, r);
				var colorRgb = this.colorToRgb(shadowColor);
				rgrd.addColorStop(1, 'rgba('+colorRgb+', 1)');
				rgrd.addColorStop(0.8, 'rgba('+colorRgb+', .7)');
				rgrd.addColorStop(0.1, "transparent");
				this.ctx.fillStyle = rgrd;
				this.ctx.fillRect(0, 0, r*2, r*2);
			},
			drawText: function(){
				this.ctx.globalCompositeOperation = 'source-over';
				var size = opts.fontSize || 0.38 * this.cR;
				this.ctx.font = 'bold ' + size + 'px Microsoft Yahei';
				var txt = (nowdata.toFixed(4) * 100).toFixed(2) + '%';
				var fonty = this.r + size / 2;
				var fontx = this.r - size * 0.8;
				this.ctx.fillStyle = textColor;
				this.ctx.textAlign = 'center';
				this.ctx.fillText(txt, this.r, this.r + this.height/10)
			},
			colorToRgb: function(sColor){		// 16进制颜色转rgb
				sColor = sColor.toLowerCase();
				var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
				if (sColor && reg.test(sColor)) {
					if (sColor.length === 4) {
						var sColorNew = "#";
						for (var i=1; i<4; i+=1) {
							sColorNew += sColor.slice(i, i+1).concat(sColor.slice(i, i+1));    
						};sColor = sColorNew;
					}
					//处理六位的颜色值
					var sColorChange = [];
					for (var i=1; i<7; i+=2) {
						sColorChange.push(parseInt("0x"+sColor.slice(i, i+2)));    
					}
					return sColorChange.join(",");
				};return sColor
			},
			clear: function(){
				this.render = null;
				cancelAnimationFrame(this.requestFrame);
				delete this.requestFrame
			},
		};return new Widget(ctn);
	};

	return {
		cuPrint, downloadFile, waveMapChart
	}
};

/**
  * 文件下载
  * @return: Object
  * @author: Kimber
  * @updatetime: 2021/7/20
  * @createtime: 2021/7/20
  */
var FileStream = function(){
	function s2ab(s) {
		var buf = new ArrayBuffer(s.length);
		var view = new Uint8Array(buf);
		for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
		return buf;
	};

	/**
	  * 字符转换 Blob 对象
	  * @param: {String} str 
	  * @example1: var aaa = FileStream.toBlob(str);
	  * @return: 
	  * @author: Kimber
	  * @updatetime: 2021/7/20
	  * @createtime: 2021/7/20
	  */
	var toBlob = function(str){
		return new Blob([s2ab(str)], {
			type: "application/octet-stream"
		});
	};
	
	/**
	  * 利用 A标签 下载文件
	  * @param: {Blob} url 
	  * @param: {String} saveName	// 文件名
	  * @example1: FileStream.download(blob, 'Test.xlsx');
	  * @return: 
	  * @author: Kimber
	  * @updatetime: 2021/7/20
	  * @createtime: 2021/7/20
	  */
	var download = function(url, saveName){
		if (typeof url == 'object' && url instanceof Blob) {
			url = URL.createObjectURL(url); // 创建blob地址
		}
		var aLink = document.createElement('a');
		aLink.href = url;
		aLink.download = saveName || ''; // HTML5新增的属性，指定保存文件名，可以不要后缀，注意，file:///模式下不会生效
		var event;
		if (window.MouseEvent) event = new MouseEvent('click');
		else {
			event = document.createEvent('MouseEvents');
			event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
		}
		aLink.dispatchEvent(event);
	};

	return {toBlob:toBlob, download:download}
};

export var Tools = Tools();
export var FileStream = FileStream();

/* exports = {
	HttpReq: HttpReq(),
	Dates: Dates(),
	Tools: Tools(),
}; */
