Vue.component("ssl-config-box", {
	props: ["v-ssl-policy", "v-protocol", "v-server-id"],
	created: function () {
		let that = this
		setTimeout(function () {
			that.sortableCipherSuites()
		}, 100)
	},
	data: function () {
		let policy = this.vSslPolicy
		if (policy == null) {
			policy = {
				id: 0,
				isOn: true,
				certRefs: [],
				certs: [],
				clientCARefs: [],
				clientCACerts: [],
				clientAuthType: 0,
				minVersion: "TLS 1.1",
				hsts: null,
				cipherSuitesIsOn: false,
				cipherSuites: [],
				http2Enabled: true
			}
		} else {
			if (policy.certRefs == null) {
				policy.certRefs = []
			}
			if (policy.certs == null) {
				policy.certs = []
			}
			if (policy.clientCARefs == null) {
				policy.clientCARefs = []
			}
			if (policy.clientCACerts == null) {
				policy.clientCACerts = []
			}
			if (policy.cipherSuites == null) {
				policy.cipherSuites = []
			}
		}

		let hsts = policy.hsts
		if (hsts == null) {
			hsts = {
				isOn: false,
				maxAge: 0,
				includeSubDomains: false,
				preload: false,
				domains: []
			}
		}

		return {
			policy: policy,

			// hsts
			hsts: hsts,
			hstsOptionsVisible: false,
			hstsDomainAdding: false,
			addingHstsDomain: "",
			hstsDomainEditingIndex: -1,

			// 相关数据
			allVersions: window.SSL_ALL_VERSIONS,
			allCipherSuites: window.SSL_ALL_CIPHER_SUITES.$copy(),
			modernCipherSuites: window.SSL_MODERN_CIPHER_SUITES,
			intermediateCipherSuites: window.SSL_INTERMEDIATE_CIPHER_SUITES,
			allClientAuthTypes: window.SSL_ALL_CLIENT_AUTH_TYPES,
			cipherSuitesVisible: false,

			// 高级选项
			moreOptionsVisible: false
		}
	},
	watch: {
		hsts: {
			deep: true,
			handler: function () {
				this.policy.hsts = this.hsts
			}
		}
	},
	methods: {
		// 删除证书
		removeCert: function (index) {
			let that = this
			teaweb.confirm("确定删除此证书吗？证书数据仍然保留，只是当前服务不再使用此证书。", function () {
				that.policy.certRefs.$remove(index)
				that.policy.certs.$remove(index)
			})
		},

		// 选择证书
		selectCert: function () {
			let that = this
			let selectedCertIds = []
			if (this.policy != null && this.policy.certs.length > 0) {
				this.policy.certs.forEach(function (cert) {
					selectedCertIds.push(cert.id.toString())
				})
			}
			teaweb.popup("/servers/certs/selectPopup?selectedCertIds=" + selectedCertIds, {
				width: "50em",
				height: "30em",
				callback: function (resp) {
					that.policy.certRefs.push(resp.data.certRef)
					that.policy.certs.push(resp.data.cert)
				}
			})
		},

		// 上传证书
		uploadCert: function () {
			let that = this
			teaweb.popup("/servers/certs/uploadPopup", {
				height: "28em",
				callback: function (resp) {
					teaweb.success("上传成功", function () {
						that.policy.certRefs.push(resp.data.certRef)
						that.policy.certs.push(resp.data.cert)
					})
				}
			})
		},

		// 申请证书
		requestCert: function () {
			// 已经在证书中的域名
			let excludeServerNames = []
			if (this.policy != null && this.policy.certs.length > 0) {
				this.policy.certs.forEach(function (cert) {
					excludeServerNames.$pushAll(cert.dnsNames)
				})
			}

			let that = this
			teaweb.popup("/servers/server/settings/https/requestCertPopup?serverId=" + this.vServerId + "&excludeServerNames=" + excludeServerNames.join(","), {
				callback: function () {
					that.policy.certRefs.push(resp.data.certRef)
					that.policy.certs.push(resp.data.cert)
				}
			})
		},

		// 更多选项
		changeOptionsVisible: function () {
			this.moreOptionsVisible = !this.moreOptionsVisible
		},

		// 格式化时间
		formatTime: function (timestamp) {
			return new Date(timestamp * 1000).format("Y-m-d")
		},

		// 格式化加密套件
		formatCipherSuite: function (cipherSuite) {
			return cipherSuite.replace(/(AES|3DES)/, "<var style=\"font-weight: bold\">$1</var>")
		},

		// 添加单个套件
		addCipherSuite: function (cipherSuite) {
			if (!this.policy.cipherSuites.$contains(cipherSuite)) {
				this.policy.cipherSuites.push(cipherSuite)
			}
			this.allCipherSuites.$removeValue(cipherSuite)
		},

		// 删除单个套件
		removeCipherSuite: function (cipherSuite) {
			let that = this
			teaweb.confirm("确定要删除此套件吗？", function () {
				that.policy.cipherSuites.$removeValue(cipherSuite)
				that.allCipherSuites = window.SSL_ALL_CIPHER_SUITES.$findAll(function (k, v) {
					return !that.policy.cipherSuites.$contains(v)
				})
			})
		},

		// 清除所选套件
		clearCipherSuites: function () {
			let that = this
			teaweb.confirm("确定要清除所有已选套件吗？", function () {
				that.policy.cipherSuites = []
				that.allCipherSuites = window.SSL_ALL_CIPHER_SUITES.$copy()
			})
		},

		// 批量添加套件
		addBatchCipherSuites: function (suites) {
			var that = this
			teaweb.confirm("确定要批量添加套件？", function () {
				suites.$each(function (k, v) {
					if (that.policy.cipherSuites.$contains(v)) {
						return
					}
					that.policy.cipherSuites.push(v)
				})
			})
		},

		/**
		 * 套件拖动排序
		 */
		sortableCipherSuites: function () {
			var box = document.querySelector(".cipher-suites-box")
			Sortable.create(box, {
				draggable: ".label",
				handle: ".icon.handle",
				onStart: function () {

				},
				onUpdate: function (event) {

				}
			})
		},

		// 显示所有套件
		showAllCipherSuites: function () {
			this.cipherSuitesVisible = !this.cipherSuitesVisible
		},

		// 显示HSTS更多选项
		showMoreHSTS: function () {
			this.hstsOptionsVisible = !this.hstsOptionsVisible;
			if (this.hstsOptionsVisible) {
				this.changeHSTSMaxAge()
			}
		},

		// 监控HSTS有效期修改
		changeHSTSMaxAge: function () {
			var v = this.hsts.maxAge
			if (isNaN(v)) {
				this.hsts.days = "-"
				return
			}
			this.hsts.days = parseInt(v / 86400)
			if (isNaN(this.hsts.days)) {
				this.hsts.days = "-"
			} else if (this.hsts.days < 0) {
				this.hsts.days = "-"
			}
		},

		// 设置HSTS有效期
		setHSTSMaxAge: function (maxAge) {
			this.hsts.maxAge = maxAge
			this.changeHSTSMaxAge()
		},

		// 添加HSTS域名
		addHstsDomain: function () {
			this.hstsDomainAdding = true
			this.hstsDomainEditingIndex = -1
			let that = this
			setTimeout(function () {
				that.$refs.addingHstsDomain.focus()
			}, 100)
		},

		// 修改HSTS域名
		editHstsDomain: function (index) {
			this.hstsDomainEditingIndex = index
			this.addingHstsDomain = this.hsts.domains[index]
			this.hstsDomainAdding = true
			let that = this
			setTimeout(function () {
				that.$refs.addingHstsDomain.focus()
			}, 100)
		},

		// 确认HSTS域名添加
		confirmAddHstsDomain: function () {
			this.addingHstsDomain = this.addingHstsDomain.trim()
			if (this.addingHstsDomain.length == 0) {
				return;
			}
			if (this.hstsDomainEditingIndex > -1) {
				this.hsts.domains[this.hstsDomainEditingIndex] = this.addingHstsDomain
			} else {
				this.hsts.domains.push(this.addingHstsDomain)
			}
			this.cancelHstsDomainAdding()
		},

		// 取消HSTS域名添加
		cancelHstsDomainAdding: function () {
			this.hstsDomainAdding = false
			this.addingHstsDomain = ""
			this.hstsDomainEditingIndex = -1
		},

		// 删除HSTS域名
		removeHstsDomain: function (index) {
			this.cancelHstsDomainAdding()
			this.hsts.domains.$remove(index)
		},

		// 选择客户端CA证书
		selectClientCACert: function () {
			let that = this
			teaweb.popup("/servers/certs/selectPopup?isCA=1", {
				width: "50em",
				height: "30em",
				callback: function (resp) {
					that.policy.clientCARefs.push(resp.data.certRef)
					that.policy.clientCACerts.push(resp.data.cert)
				}
			})
		},

		// 上传CA证书
		uploadClientCACert: function () {
			let that = this
			teaweb.popup("/servers/certs/uploadPopup?isCA=1", {
				height: "28em",
				callback: function (resp) {
					teaweb.success("上传成功", function () {
						that.policy.clientCARefs.push(resp.data.certRef)
						that.policy.clientCACerts.push(resp.data.cert)
					})
				}
			})
		},

		// 删除客户端CA证书
		removeClientCACert: function (index) {
			let that = this
			teaweb.confirm("确定删除此证书吗？证书数据仍然保留，只是当前服务不再使用此证书。", function () {
				that.policy.clientCARefs.$remove(index)
				that.policy.clientCACerts.$remove(index)
			})
		}
	},
	template: `<div>
	<h4>SSL/TLS相关配置</h4>
	<input type="hidden" name="sslPolicyJSON" :value="JSON.stringify(policy)"/>
	<table class="ui table definition selectable">
		<tbody>
			<tr v-show="vProtocol == 'https'">
				<td class="title">启用HTTP/2</td>
				<td>
					<div class="ui checkbox">
						<input type="checkbox" value="1" v-model="policy.http2Enabled"/>
						<label></label>
					</div>
				</td>
			</tr>
			<tr>
				<td class="title">选择证书</td>
				<td>
					<div v-if="policy.certs != null && policy.certs.length > 0">
						<div class="ui label small" v-for="(cert, index) in policy.certs">
							{{cert.name}} / {{cert.dnsNames}} / 有效至{{formatTime(cert.timeEndAt)}} &nbsp; <a href="" title="删除" @click.prevent="removeCert(index)"><i class="icon remove"></i></a>
						</div>
						<div class="ui divider"></div>
					</div>
					<div v-else>
						<span class="red">选择或上传证书后<span v-if="vProtocol == 'https'">HTTPS</span><span v-if="vProtocol == 'tls'">TLS</span>服务才能生效。</span>
						<div class="ui divider"></div>
					</div>
					<button class="ui button tiny" type="button" @click.prevent="selectCert()">选择已有证书</button> &nbsp;
					<button class="ui button tiny" type="button" @click.prevent="uploadCert()">上传新证书</button> &nbsp;
					<button class="ui button tiny" type="button" @click.prevent="requestCert()" v-if="vServerId != null && vServerId > 0">申请免费证书</button>
				</td>
			</tr>
			<tr>
				<td>TLS最低版本</td>
				<td>
					<select v-model="policy.minVersion" class="ui dropdown auto-width">
						<option v-for="version in allVersions" :value="version">{{version}}</option>
					</select>
				</td>
			</tr>
		</tbody>
		<more-options-tbody @change="changeOptionsVisible"></more-options-tbody>
		<tbody v-show="moreOptionsVisible">
			<!-- 加密套件 -->
			<tr>
				<td>加密算法套件<em>（CipherSuites）</em></td>
				<td>
					<div class="ui checkbox">
						<input type="checkbox" value="1" v-model="policy.cipherSuitesIsOn" />
						<label>是否要自定义</label>
					</div>
					<div v-show="policy.cipherSuitesIsOn">
						<div class="ui divider"></div>
						<div class="cipher-suites-box">
							已添加套件({{policy.cipherSuites.length}})：
							<div v-for="cipherSuite in policy.cipherSuites" class="ui label tiny basic" style="margin-bottom: 0.5em">
								<input type="hidden" name="cipherSuites" :value="cipherSuite"/>
								<span v-html="formatCipherSuite(cipherSuite)"></span> &nbsp; <a href="" title="删除套件" @click.prevent="removeCipherSuite(cipherSuite)"><i class="icon remove"></i></a>
								<a href="" title="拖动改变顺序"><i class="icon bars handle"></i></a>
							</div>
						</div>
						<div>
							<div class="ui divider"></div>
							<span v-if="policy.cipherSuites.length > 0"><a href="" @click.prevent="clearCipherSuites()">[清除所有已选套件]</a> &nbsp; </span>
							<a href="" @click.prevent="addBatchCipherSuites(modernCipherSuites)">[添加推荐套件]</a> &nbsp;
							<a href="" @click.prevent="addBatchCipherSuites(intermediateCipherSuites)">[添加兼容套件]</a>
							<div class="ui divider"></div>
						</div>
		
						<div class="cipher-all-suites-box">
							<a href="" @click.prevent="showAllCipherSuites()"><span v-if="policy.cipherSuites.length == 0">所有</span>可选套件({{allCipherSuites.length}}) <i class="icon angle" :class="{down:!cipherSuitesVisible, up:cipherSuitesVisible}"></i></a>
							<a href="" v-if="cipherSuitesVisible" v-for="cipherSuite in allCipherSuites" class="ui label tiny" title="点击添加到自定义套件中" @click.prevent="addCipherSuite(cipherSuite)" v-html="formatCipherSuite(cipherSuite)" style="margin-bottom:0.5em"></a>
						</div>
						<p class="comment" v-if="cipherSuitesVisible">点击可选套件添加。</p>
					</div>
				</td>
			</tr>
			
			<!-- HSTS -->
			<tr v-show="vProtocol == 'https'">
				<td :class="{'color-border':hsts.isOn}">是否开启HSTS</td>
				<td>
					<div class="ui checkbox">
						<input type="checkbox" name="hstsOn" v-model="hsts.isOn" value="1"/>
						<label></label>
					</div>
					<p class="comment">
						 开启后，会自动在响应Header中加入
						 <span class="ui label small">Strict-Transport-Security:
							 <var v-if="!hsts.isOn">...</var>
							 <var v-if="hsts.isOn"><span>max-age=</span>{{hsts.maxAge}}</var>
							 <var v-if="hsts.isOn && hsts.includeSubDomains">; includeSubDomains</var>
							 <var v-if="hsts.isOn && hsts.preload">; preload</var>
						 </span>
						  <span v-if="hsts.isOn">
							<a href="" @click.prevent="showMoreHSTS()">修改<i class="icon angle" :class="{down:!hstsOptionsVisible, up:hstsOptionsVisible}"></i> </a>
						 </span>
					</p>
				</td>
			</tr>
			<tr v-show="hsts.isOn && hstsOptionsVisible">
				<td class="color-border">HSTS包含子域名<em>（includeSubDomains）</em></td>
				<td>
					<div class="ui checkbox">
						<input type="checkbox" name="hstsIncludeSubDomains" value="1" v-model="hsts.includeSubDomains"/>
						<label></label>
					</div>
				</td>
			</tr>
			<tr v-show="hsts.isOn && hstsOptionsVisible">
				<td class="color-border">HSTS预加载<em>（preload）</em></td>
				<td>
					<div class="ui checkbox">
						<input type="checkbox" name="hstsPreload" value="1" v-model="hsts.preload"/>
						<label></label>
					</div>
				</td>
			</tr>
			<tr v-show="hsts.isOn && hstsOptionsVisible">
				<td class="color-border">HSTS生效的域名</td>
				<td colspan="2">
					<div class="names-box">
					<span class="ui label tiny basic" v-for="(domain, arrayIndex) in hsts.domains" :class="{blue:hstsDomainEditingIndex == arrayIndex}">{{domain}}
						<input type="hidden" name="hstsDomains" :value="domain"/> &nbsp;
						<a href="" @click.prevent="editHstsDomain(arrayIndex)" title="修改"><i class="icon pencil"></i></a>
						<a href="" @click.prevent="removeHstsDomain(arrayIndex)" title="删除"><i class="icon remove"></i></a>
					</span>
					</div>
					<div class="ui fields inline" v-if="hstsDomainAdding" style="margin-top:0.8em">
						<div class="ui field">
							<input type="text" name="addingHstsDomain" ref="addingHstsDomain" style="width:16em" maxlength="100" placeholder="域名，比如example.com" @keyup.enter="confirmAddHstsDomain()" @keypress.enter.prevent="1" v-model="addingHstsDomain" />
						</div>
						<div class="ui field">
							<button class="ui button tiny" type="button" @click="confirmAddHstsDomain()">确定</button>
							&nbsp; <a href="" @click.prevent="cancelHstsDomainAdding()">取消</a>
						</div>
					</div>
					<div class="ui field" style="margin-top: 1em">
						<button class="ui button tiny" type="button" @click="addHstsDomain()">+</button>
					</div>
					<p class="comment">如果没有设置域名的话，则默认支持所有的域名。</p>
				</td>
			</tr>
			
			<!-- 客户端认证 -->
			<tr>
				<td>客户端认证方式</td>
				<td>
					<select name="clientAuthType" v-model="policy.clientAuthType" class="ui dropdown auto-width">
						<option v-for="authType in allClientAuthTypes" :value="authType.type">{{authType.name}}</option>
					</select>
				</td>
			</tr>
			<tr>
				<td>客户端认证CA证书</td>
				<td>
					<div v-if="policy.clientCACerts != null && policy.clientCACerts.length > 0">
						<div class="ui label small" v-for="(cert, index) in policy.clientCACerts">
							{{cert.name}} / {{cert.dnsNames}} / 有效至{{formatTime(cert.timeEndAt)}} &nbsp; <a href="" title="删除" @click.prevent="removeClientCACert()"><i class="icon remove"></i></a>
						</div>
						<div class="ui divider"></div>
					</div>
					<button class="ui button tiny" type="button" @click.prevent="selectClientCACert()">选择已有证书</button> &nbsp;
					<button class="ui button tiny" type="button" @click.prevent="uploadClientCACert()">上传新证书</button>
					<p class="comment">用来校验客户端证书以增强安全性，通常不需要设置。</p>
				</td>
			</tr>
		</tbody>	
	</table>
	<div class="ui margin"></div>
</div>`
})