<template>
	<view>
		<view class="main-box">
			<!-- 	<uni-popup ref="popup" type="dialog">
			    <uni-popup-dialog mode="input" message="成功消息" :duration="2000" :before-close="true" @close="close" @confirm="confirm"></uni-popup-dialog>
			</uni-popup> -->
			<uni-fab ref="entityFab" class="menuStyle" :content="menuContent" @trigger="menuClick"></uni-fab>
			<view class="content-window">
				<scroll-view class="entity-area" scroll-y="true">
					<movable-area ref="contentArea">
						<thirdlucky-uml-entity
							v-for="(table, index) in tables"
							:ref="table.key"
							:x="table.x"
							:y="table.y"
							:key="table.key"
							:entityName="table.name"
							:title="table.title"
							:columns="table.columns"
							:style="{ order: index }"
							@start="onStart"
							@end="onEnd"
						/>
					</movable-area>
				</scroll-view>
				<view ref="consoleView" class="console-view">
					<textarea ref="consoleText" class="text-area" v-model="texts" @linechange="onLineChange" disabled="true" :selection-end="positionY"></textarea>
					<!-- <rich-text ref="consoleText" class="text-area" :nodes="nodes"></rich-text> -->
				</view>
			</view>
			<movable-area ref="toolBar" class="tool-bar">
				<view class="title-bar">工具栏</view>
				<thirdlucky-uml-entity ref="entityTool" :x="offsetX" :y="offsetY" entityName="entity" title="实体" @start="onStartTool" @end="onEndTool" />
			</movable-area>
			<view ref="propertyBar" class="property-bar">
				<view class="title-bar">实体信息</view>
				<view class="entity_info">
					<uni-forms-item class="form-item" label="名称"><uni-easyinput :focus="focus.entityName" v-model="_entityName" placeholder="请输入表名" /></uni-forms-item>
					<uni-forms-item class="form-item" label="标题"><uni-easyinput v-model="_entityTitle" placeholder="请输入标题" /></uni-forms-item>
					<uni-forms-item class="form-item" label="描述"><uni-easyinput v-model="_entityInfo" placeholder="请输入描述" /></uni-forms-item>
				</view>
				<scroll-view class="property-table" scroll-y="true">
					<thirdlucky-data-table ref="tableView" actions="+-" border stripe :datas="_columns" :columns="schemas" @selected="onSelected"></thirdlucky-data-table>
				</scroll-view>
				<view class="property-info">
					<thirdlucky-data-form ref="propertyView" :formData="column" :columns="columnSchemas" @confirm="onConfirm" @changed="onChanged"></thirdlucky-data-form>
				</view>
			</view>
		</view>
	</view>
</template>
<script>
let defaultX = 20;
let defaultY = 40;
let defaultTable = { key: 'default' };

let spaceX = 180;
let spaceY = 260;
let rowCount = 5;

let idColumn = { name: 'id', type: 'bigint', info: '主键', pk: true };
let descriptionColumn = { name: 'description', type: 'text', info: '描述', pk: false };
let passwordColumn = { name: 'password', type: 'password', info: '密码', pk: false };
export default {
	data() {
		return {
			positionY: 0,
			selected: 0,
			texts: '',
			config: {
				followName: true
			},
			x: 0,
			y: 0,
			menuContent: [{ text: '删除' }, { text: '读取' }, { text: '建库' }, { text: '读库' }, { text: '代码' }],
			offsetX: defaultX,
			offsetY: defaultY,
			tables: [],
			columnSchemas: [
				{
					name: 'name',
					info: '列名',
					tips: '',
					type: 'text'
				},
				{
					name: 'type',
					info: '类型',
					tips: '',
					type: 'enum',
					values: [
						{
							text: '文本',
							value: 'varchar'
						},
						{
							text: '长文本',
							value: 'text'
						},
						{
							text: '字符',
							value: 'char'
						},
						{
							text: '超长文本',
							value: 'longtext'
						},
						{
							text: 'json',
							value: 'json'
						},
						{
							text: '长对象',
							value: 'blob'
						},
						{
							text: '超长对象',
							value: 'longblob'
						},
						{
							text: '二进制',
							value: 'binary'
						},
						{
							text: '变二进制',
							value: 'varbinary'
						},
						{
							text: '长整型',
							value: 'bigint'
						},
						{
							text: '整型',
							value: 'int'
						},
						{
							text: '整型8',
							value: 'tinyint'
						},
						{
							text: '整型16',
							value: 'smallint'
						},
						{
							text: '十进制',
							value: 'decimal'
						},
						{
							text: '浮点',
							value: 'float'
						},
						{
							text: '双浮点',
							value: 'double'
						},
						{
							text: '日期',
							value: 'date'
						},
						{
							text: '日期时间',
							value: 'datetime'
						},
						{
							text: '时间',
							value: 'time'
						},

						{
							text: '时间戳',
							value: 'timestamp'
						},
						{
							text: '开关',
							value: 'bit'
						}
					]
				},
				{
					name: 'info',
					info: '描述',
					tips: '',
					type: 'text'
				},
				{
					name: 'pk',
					info: '主键',
					tips: '',
					type: 'switch'
				}
			],
			schemas: [
				{
					name: 'name',
					info: '列名',
					tips: '',
					type: 'text'
				}
			],
			table: defaultTable,
			column: {},
			focus: {
				entityName: false,
				columnName: false
			}
		};
	},

	computed: {
		_entityName: {
			get() {
				return this.table.name;
			},
			set(val) {
				this.table.name = val;
			}
		},
		_entityTitle: {
			get() {
				return this.table.title;
			},
			set(val) {
				this.table.title = val;
			}
		},
		_entityInfo: {
			get() {
				return this.table.info;
			},
			set(val) {
				this.table.info = val;
			}
		},
		_columns: {
			get() {
				if (this.table != 'undefined') {
					return this.table.columns;
				} else {
					return null;
				}
			}
		}
	},
	methods: {
		appendText(text) {
			console.log(text);
			let line =  "\t" + text + "\n";
			this.texts += line;
		},
		confirm() {},

		t2e() {
			let entities = [];
			for (let table of this.tables) {
				entities.push(this.table2Entity(table));
			}
			return entities;
		},
		e2t(entities) {
			let tables = [];
			for (let entity of entities) {
				if (entity.show) {
					tables.push(this.entity2Table(entity));
				}
			}
			this.tables = tables;
		},
		table2Entity(table) {
			let fields = [];
			for (let column of table.columns) {
				fields.push(this.column2Field(column));
			}
			return { name: table.name, title: table.title, comment: table.info, show: true, fields: fields };
		},
		entity2Table(entity) {
			let columns = [];
			for (let field of entity.fields) {
				columns.push(this.field2Column(field));
			}
			return { name: entity.name, title: entity.title, info: entity.comment, domainId: entity.domainId, columns: columns };
		},

		column2Field(column) {
			return { name: column.name, comment: column.info, show: true, pk: column.pk, type: column.type };
		},

		field2Column(field) {
			return { entityId: field.entityId, name: field.name, info: field.comment, show: field.show, pk: field.pk, type: field.type };
		},

		delteEntity() {
			if (this.table != null || this.table != defaulTable) {
				let index = this.tables.indexOf(this.table);
				this.tables.splice(index, 1);
				this.table = defaultTable;
			}
			this.$refs.entityFab.close();
		},
		arrangeEntities() {
			for (let i = 0; i < this.tables.length; i++) {
				let table = this.tables[i];
				let v = parseInt(i / rowCount);
				table.x = (i % rowCount) * spaceX + defaultX;
				table.y = v * spaceY + defaultY;
			}
		},
		loadEntities() {
			this.appendText('读取模型...');

			let _this = this;
			uni.showModal({
				title: '请输入领域id',
				content: '1',
				editable: true,
				success: function(res) {
					if (res.confirm) {
						let i = parseInt(res.content);
						_this.loadByModel(i);
					} else if (res.cancel) {
						this.appendText('用户点击取消');
					}
				}
			});
		},
		loadByModel(domainId) {
			this.api.loadEntities(
				domainId,
				res => {
					uni.showToast({
						title: '读取成功:' + domainId,
						icon: 'succes',
						duration: 2000
					});
					this.e2t(res.data.data);
					this.arrangeEntities();
				},
				res => {
					uni.showToast({
						title: '读取失败:' + res.errMsg,
						icon: 'error',
						duration: 2000
					});
				}
			);
		},

		createDb() {
			this.appendText('建库...');
			let _this = this;
			uni.showModal({
				title: '请输入数据源id',
				content: '1',
				editable: true,
				success: function(res) {
					if (res.confirm) {
						let i = parseInt(res.content);
						_this.createDataSource(i);
					} else if (res.cancel) {
						this.appendText('用户点击取消');
					}
				}
			});
		},
		createDataSource(sourceId) {
			let entities = this.t2e();
			this.api.createDb(
				sourceId,
				entities,
				res => {
					uni.showToast({
						title: '建库成功:' + sourceId,
						icon: 'succes',
						duration: 2000
					});
				},
				res => {
					uni.showToast({
						title: '建库失败:' + res.errMsg,
						icon: 'error',
						duration: 2000
					});
				}
			);
		},
		loadDb() {
			this.appendText('读库...');

			let _this = this;
			uni.showModal({
				title: '请输入数据源id',
				content: '1',
				editable: true,
				success: function(res) {
					if (res.confirm) {
						let i = parseInt(res.content);
						_this.loadDataSource(i);
					} else if (res.cancel) {
						this.appendText('用户点击取消');
					}
				}
			});
		},

		loadDataSource(sourceId) {
			this.api.loadDb(
				sourceId,
				res => {
					let data = res.data;
					if (data.errCode == 0) {
						uni.showToast({
							title: '读库成功:' + sourceId,
							icon: 'succes',
							duration: 2000
						});
						this.e2t(res.data.data);
						this.arrangeEntities();
					} else {
						uni.showToast({
							title: '读库失败:' + data.message,
							icon: 'error',
							duration: 2000
						});
					}
				},
				res => {
					uni.showToast({
						title: '读库失败:' + res.errMsg,
						icon: 'error',
						duration: 2000
					});
				}
			);
		},

		generateCode() {
			this.appendText('生成代码...');

			let _this = this;
			uni.showModal({
				title: '请输入组件id',
				content: '1',
				editable: true,
				success: function(res) {
					if (res.confirm) {
						let i = parseInt(res.content);
						_this.createCode(i);
					} else if (res.cancel) {
						this.appendText('用户点击取消');
					}
				}
			});
		},

		createCode(componentId) {
			this.api.generateCode(
				componentId,
				res => {
					let data = res.data;
					if (data.errCode == 0) {
						uni.showToast({
							title: '生成成功:' + componentId,
							icon: 'succes',
							duration: 2000
						});
					} else {
						uni.showToast({
							title: '生成失败:' + data.message,
							icon: 'error',
							duration: 2000
						});
					}
				},
				res => {
					this.appendText('生成失败:' + res.errMsg);
					uni.showToast({
						title: '生成失败:' + res.errMsg,
						icon: 'error',
						duration: 2000
					});
				}
			);
		},

		saveEntities() {
			this.appendText('存储模型...');

			let _this = this;
			uni.showModal({
				title: '请输入领域id',
				content: '1',
				editable: true,
				success: function(res) {
					if (res.confirm) {
						let i = parseInt(res.content);
						_this.saveModel(i);
					} else if (res.cancel) {
						this.appendText('用户点击取消');
					}
				}
			});
		},
		saveModel(domainId) {
			let entities = this.t2e();
			this.api.saveEntities(
				domainId,
				entities,
				res => {
					uni.showToast({
						title: '提交成功:' + domainId,
						icon: 'succes',
						duration: 2000
					});
				},
				res => {
					uni.showToast({
						title: '提交失败:' + res.errMsg,
						icon: 'error',
						duration: 2000
					});
				}
			);
		},
		menuClick(e) {
			switch (e.index) {
				case 0:
					this.delteEntity();
					break;
				case 1:
					this.loadEntities();
					break;
				case 2:
					this.createDb();
					break;
				case 3:
					this.loadDb();
					break;
				case 4:
					this.generateCode();
					break;
			}
			this.$refs.entityFab.close();
		},
		deleteColumn(col) {
			let columns = this.table.columns;
			let index = columns.indexOf(col);
			columns.splice(index, 1);
			if (columns.length == 0) {
				this.refreshColumns();
			}
		},
		addColumn(col) {
			let propertyView = this.$refs.propertyView;
			propertyView.focusItem(0);
		},
		refreshColumns() {
			let columns = this.table.columns;
			if (columns != null && columns.length > 0) {
				let column = columns[0];
				this.onSelected(0, 'select', column);
			} else {
				this.onSelected(-1, 'select', {});
			}
		},
		onSelected(rindex, action, column) {
			this.column = column;
			switch (action) {
				case 'edit':
					break;
				case 'delete':
					this.deleteColumn(column);
					break;
				case 'select':
					break;
				case 'add':
					this.addColumn(column);
					break;
			}
		},
		followName(colName, val) {
			let column = this.types.forName(val);
			if (column != null) {
				this.types.copyWithoutName(column, this.column);
			}
		},
		onChanged(colName, newVal, oldVal) {
			this.appendText('changed:new=' + colName + ',old=' + oldVal);
			if (this.config.followName) {
				this.followName(colName, newVal);
			}
		},
		onConfirm(action, data) {
			if (action == 'submit') {
				this.saveEntities();
			} else {
				this.appendText('提交取消');
			}
		},
		resetTool() {
			if (this.offsetX == defaultX) {
				this.offsetX += 0.0000001;
			} else {
				this.offsetX = defaultX;
			}
		},
		onStart(key, event, x, y, table) {
			this.focus.entityName = false;
		},
		onEnd(key, event, x, y, table) {
			this.showEntity(key);
		},
		onStartTool(key, event, x, y, table) {
			this.focus.entityName = false;
		},
		onEndTool(key, event, x, y, table) {
			this.addEntity(x, y);
		},
		onLineChange(e) {
			this.positionY = e.detail.height;
		},
		addEntity(x, y) {
			let tool = this.$refs.toolBar;
			let w = tool.width;
			let _x = x - w + defaultX;
			let _y = y + defaultY;

			if (_x >= 0) {
				let number = this.getNewNumber();
				let table = this.createTableWithNumber(_x, _y, number);
				this.tables.push(table);
				this.showEntity(table.name);
			}
			this.resetTool();
		},
		showEntity(key) {
			let table = this.tables.find(t => t.name == key);
			if (this.table != table) {
				this.table = table;
				this.refreshColumns();
				this.focus.entityName = true;
			}
		},
		getNewNumber() {
			let number = this.tables.length;
			while (true) {
				let name = 'entity' + number;
				let i = this.tables.findIndex(tab => {
					return tab.name == name;
				});
				if (i < 0) {
					break;
				}
				number++;
			}
			return number;
		},
		createTableWithNumber(x, y, number) {
			let title = '实体' + number;
			let name = 'entity' + number;
			return { x: x, y: y, index: number, title: title, name: name, info: '', columns: [this.tools.clone(idColumn)] };
		}
	}
};
</script>

<style lang="scss">
$window-height: 93vh;
$border-width: 5rpx;
$control-width: 200rpx;
$control-height: 200rpx;

$tool-bar-index: 100;
$content-bar-index: 0;
$property-bar-index: 200;
$menu-index: 201;

$title-bar-backcolor: #2d8cf0;
$property-bar-back-color: #ffffff;

.main-box {
	display: flex;
	flex-direction: row;
	justify-content: space-between;
}
.tool-bar {
	order: 1;
	flex: 1;
	height: $window-height;
	background-color: #c1c1c1;
	border-style: solid;
	border-width: $border-width;
	z-index: $tool-bar-index;
}
.content-window {
	order: 2;
	flex: 7;
	margin-left: -$border-width;
	height: $window-height;
	border-style: solid;
	border-width: $border-width;
	background-color: #282c35;
	display: flex;
	flex-direction: column;
	flex-wrap: wrap;
	z-index: $content-bar-index;
}
.entity-area {
	flex: 4;
}
.console-view {
	background: white;
	border-style: solid;
	border-width: $border-width;
	flex: 1;
}
.text-area {
	width: 100%;
	height: 100%;
}
.property-bar {
	order: 3;
	flex: 2;
	border-style: solid;
	border-width: $border-width;
	margin-left: -$border-width;
	height: $window-height;
	background-color: $property-bar-back-color;
	z-index: $property-bar-index;
}
.menuStyle {
	z-index: $menu-index;
}
.title-bar {
	width: 100%;
	background-color: $title-bar-backcolor;
	color: white;
}
.property-table {
	order: 1;
	height: 30%;
}
.property-info {
	order: 2;
	flex: 1;
	position: absolute;
	bottom: 0;
	height: 40%;
	width: 20%;
}
.table-info {
	display: flex;
	flex-direction: row;
}
.table-info-label {
	font-size: 0.95em;
	bottom: 0;
}
.entity_info {
	padding: 20rpx 15rpx 0rpx 10rpx;
	border-width: 1rpx;
}
.div-class {
	display: flex;
	flex-direction: column;
}
</style>
