<template>
	<view>
		<u-popup :show="show" round="15" mode="center" :closeable="true" :customStyle="{ width: '95%' }" @close="cancelSignature">
			<view class="popup">
				<view class="signature-contain">
					<view class="signature-main">
						<view class="title">请签字</view>
						<canvas disable-scroll="true" class="signature" :class="cid" canvas-id="cvs" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"></canvas>
						<view class="signature-btns">
							<button class="btn" style="background-color: #9e9e9e" @tap="cancelSignature()">取消</button>
							<button class="btn" @tap="onOK()">确定</button>
						</view>
					</view>
				</view>
			</view>
		</u-popup>
	</view>
</template>

<script>
let _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var _utf8_encode = function (string) {
	string = string.replace(/\r\n/g, '\n');
	var utftext = '';
	for (var n = 0; n < string.length; n++) {
		var c = string.charCodeAt(n);
		if (c < 128) {
			utftext += String.fromCharCode(c);
		} else if (c > 127 && c < 2048) {
			utftext += String.fromCharCode((c >> 6) | 192);
			utftext += String.fromCharCode((c & 63) | 128);
		} else {
			utftext += String.fromCharCode((c >> 12) | 224);
			utftext += String.fromCharCode(((c >> 6) & 63) | 128);
			utftext += String.fromCharCode((c & 63) | 128);
		}
	}
	return utftext;
};

let base64encode = function (input) {
	var output = '';
	var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
	var i = 0;
	input = _utf8_encode(input);
	while (i < input.length) {
		chr1 = input.charCodeAt(i++);
		chr2 = input.charCodeAt(i++);
		chr3 = input.charCodeAt(i++);
		enc1 = chr1 >> 2;
		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
		enc4 = chr3 & 63;
		if (isNaN(chr2)) {
			enc3 = enc4 = 64;
		} else if (isNaN(chr3)) {
			enc4 = 64;
		}
		output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
	}
	return output;
};
export default {
	cxt: null,
	data() {
		return {
			ip: this.http.ip,
			VERSION: '1.0.0',
			cid: 'cvs',
			show: false,
			ctrl: null,
			listeners: [],
			prevView: '',

			draws: [],
			lines: [],
			line: null
		};
	},
	props: {
		value: {
			default: ''
		},
		title: {
			type: String,
			default: '请签字'
		},
		disabled: {
			type: Boolean,
			default: false
		}
	},
	watch: {
		value() {
			this.prevView = this.value;
		}
	},
	computed: {
		titles() {
			return this.title.split('');
		},
		absPrevView() {
			var pv = this.prevView;
			// if(pv){
			// 	pv = this.$wrapUrl(pv)
			// }
			return pv;
		}
	},
	mounted() {
		this.prevView = this.value;
	},
	methods: {
		onOK() {
			uni.showModal({
				title: '提示',
				content: '确定提交签名并签约?',
				success: (res) => {
					if (res.confirm) {
						uni.canvasToTempFilePath(
							{
								canvasId: this.cid,
								fileType: 'png',
								quality: 1, //图片质量
								success: (res) => {
									uni.uploadFile({
										url: this.ip + '/app/common/upload',
										filePath: res.tempFilePath,
										name: 'file',
										header: { Authorization: this.getUser().token },
										success: (res) => {
											let data = JSON.parse(res.data);
											if (data.code == 200) {
												this.$emit('sign', data.fileName);
												this.hideSignature();
											} else {
												uni.showModal({ content: data.msg, showCancel: false });
											}
											uni.hideLoading();
										},
										fail: (res) => {
											uni.hideLoading();
											uni.showModal({ content: '图片上传失败', showCancel: false });
										}
									});
								},
								fail: (err) => {}
							},
							this
						);
					}
				}
			});
		},
		touchSignature() {
			let sig = this.prevView;
			if (!sig || !sig.length) {
				this.showSignature();
			}
		},
		showSignature() {
			if (this.disabled) return;
			if (!this.ctrl) {
				this.initCtrl();
			} else if (!this.show) {
				this.clearSignature();
				this.show = true;
			}
		},
		async getSyncSignature() {
			this.showSignature();
			return await new Promise(async (resolve, reject) => {
				this.listeners.push((res) => {
					resolve(res);
				});
			});
		},
		cancelSignature() {
			this.listeners.map((f) => {
				f(null);
			});
			this.hideSignature();
		},
		hideSignature() {
			this.ctrl && this.ctrl.clear();
			this.show = false;
		},
		clearSignature() {
			this.ctrl && this.ctrl.clear();
		},
		async initCtrl() {
			this.show = true;
			let cxt = uni.createCanvasContext(this.cid, this);
			this.cxt = cxt;
			// cxt.clearRect(0,0,c.width,c.height);
			this.ctrl = {
				width: 0,
				height: 0,
				clear: () => {
					this.lines = [];
					let info = uni
						.createSelectorQuery()
						.in(this)
						.select('.' + this.cid);
					info.boundingClientRect((data) => {
						if (data) {
							cxt.clearRect(0, 0, data.width, data.height);
							if (data.width && data.height) {
								this.ctrl.width = data.width;
								this.ctrl.height = data.height;
							}
						}
					}).exec();
					this.redraw();
				},
				getValue: () => {
					if (!this.lines.length) return '';
					let svg = this._get_svg();
					// new Buff
					let b64 = base64encode(svg);
					let data = 'data:image/svg+xml;base64,' + b64;
					// console.log(svg);
					// console.log(data);
					return data;
				}
			};
			this.$nextTick(function () {
				this.ctrl.clear();
			});
		},
		_get_svg() {
			let r = -90;
			let paths = [];
			let raww = this.ctrl.width;
			let rawh = this.ctrl.height;
			let width = Math.abs(r) != 90 ? raww : rawh;
			let height = Math.abs(r) == 90 ? raww : rawh;
			let cx = raww / 2;
			let cy = rawh / 2;
			let PI = Math.PI;
			let R = (r || 0) % 360;
			let cosv = Math.cos((R * PI) / 180);
			let sinv = Math.sin((R * PI) / 180);
			let dcx = (width - raww) / 2;
			let dcy = (height - rawh) / 2;
			let trans = function (p) {
				if (!R) {
					return p;
				} else {
					let nx = (p.x - cx) * cosv - (p.y - cy) * sinv + cx;
					let ny = (p.x - cx) * sinv + (p.y - cy) * cosv + cy;
					return {
						x: nx + dcx,
						y: ny + dcy
					};
				}
				return p;
			};
			this.lines.map((l) => {
				if (l.points.length < 2) {
					return;
				}
				let sp = trans(l.start);
				let pts = [`M ${sp.x} ${Number(sp.y)}`];
				l.points.map((p) => {
					let np = trans(p);
					pts.push(`L ${np.x} ${Number(np.y)}`);
				});
				paths.push(`<path stroke-linejoin="round" stroke-linecap="round" stroke-width="3" stroke="rgb(0,0,0)" fill="none" d="${pts.join(' ')}"/>`);
			});
			let svg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="${width}" height="${height}">${paths.join(
				'\n'
			)}</svg>`;
			return svg;
		},
		_get_svg_raw() {
			let paths = [];
			this.lines.map((l) => {
				if (l.points.length < 2) {
					return;
				}
				let pts = [`M ${l.start.x} ${Number(l.start.y)}`];
				l.points.map((p) => {
					pts.push(`L ${p.x} ${Number(p.y)}`);
				});
				paths.push(`<path stroke-linejoin="round" stroke-linecap="round" stroke-width="3" stroke="rgb(0,0,0)" fill="none" d="${pts.join(' ')}"/>`);
			});
			let width = this.ctrl.width;
			let height = this.ctrl.height;
			let svg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="${width}" height="${height}" transform="rotate(-90)">${paths.join(
				'\n'
			)}</svg>`;
			return svg;
		},
		_get_point(e) {
			return {
				x: e.changedTouches[0].x.toFixed(1),
				y: e.changedTouches[0].y.toFixed(1)
			};
		},
		touchstart(e) {
			let p = this._get_point(e);
			this.line = {
				start: p,
				points: [p]
			};
			this.lines.push(this.line);
		},
		touchmove(e) {
			let p = this._get_point(e);
			this.line.points.push(p);
			if (!this.tm) {
				this.tm = setTimeout(() => {
					this.redraw();
					this.tm = 0;
				}, 10);
			}
		},
		touchend(e) {
			let p = this._get_point(e);
			this.line.points.push(p);
			this.line.end = p;
			this.redraw();
		},
		redraw() {
			let cxt = this.cxt;
			cxt.setStrokeStyle('#000');
			cxt.setLineWidth(3);
			var last = null;
			this.lines.map((l) => {
				cxt.beginPath();
				if (l.points.length < 2) {
					return;
				}
				cxt.moveTo(l.start.x, l.start.y);
				l.points.map((p) => {
					cxt.lineTo(p.x, p.y);
				});
				cxt.stroke();
			});

			cxt.draw();
		},
		canvasIdErrorCallback: function (e) {
			console.error(e.detail.errMsg);
		}
	}
};
</script>

<style lang="scss">
.signature-contain {
	width: 100%;
	.signature-main {
		.title {
			text-align: center;
		}
		.signature {
			width: 100%;
			border: 1px dotted black;
			border-bottom: 1px dotted black;
			margin: 10px 0;
		}
		.btn {
			margin-top: 10px;
		}
	}
}
</style>