text: 'use strict';
  
  const path = require('path');
  const fs = require('fs');
  
  const ConfigUtil = require(__dirname + '/../utils/config-util.js');
  const SystemUtil = require(__dirname + '/../utils/system-util.js');
  const { app, dialog } = require('electron').remote;
  
  const BaseComponent = require(__dirname + '/../components/base.js');
  const handleExternalLink = require(__dirname + '/../components/handle-external-link.js');
  
  const shouldSilentWebview = ConfigUtil.getConfigItem('silent');
  class WebView extends BaseComponent {
  	constructor(props) {
  		super();
  
  		this.props = props;
  
  		this.zoomFactor = 1.0;
  		this.loading = true;
  		this.badgeCount = 0;
  		this.customCSS = ConfigUtil.getConfigItem('customCSS');
  		this.$webviewsContainer = document.querySelector('#webviews-container').classList;
  	}
  
  	template() {
  		return `<webview
  					class="disabled"
  					data-tab-id="${this.props.tabIndex}"
  					src="${this.props.url}"
  					${this.props.nodeIntegration ? 'nodeIntegration' : ''}
  					disablewebsecurity
  					${this.props.preload ? 'preload="js/preload.js"' : ''}
  					partition="persist:webviewsession"
  					name="${this.props.name}"
  					webpreferences="allowRunningInsecureContent, javascript=yes">
  				</webview>`;
  	}
  
  	init() {
  		this.$el = this.generateNodeFromTemplate(this.template());
  		this.props.$root.appendChild(this.$el);
  
  		this.registerListeners();
  	}
  
  	registerListeners() {
  		this.$el.addEventListener('new-window', event => {
  			handleExternalLink.call(this, event);
  		});
  
  		if (shouldSilentWebview) {
  			this.$el.addEventListener('dom-ready', () => {
  				this.$el.setAudioMuted(true);
  			});
  		}
  
  		this.$el.addEventListener('page-title-updated', event => {
  			const { title } = event;
  			this.badgeCount = this.getBadgeCount(title);
  			this.props.onTitleChange();
  		});
  
  		this.$el.addEventListener('did-navigate-in-page', event => {
  			const isSettingPage = event.url.includes('renderer/preference.html');
  			if (isSettingPage) {
  				return;
  			}
  			this.canGoBackButton();
  		});
  
  		this.$el.addEventListener('did-navigate', () => {
  			this.canGoBackButton();
  		});
  
  		this.$el.addEventListener('page-favicon-updated', event => {
  			const { favicons } = event;
  
  			// This returns a string of favicons URL. If there is a PM counts in unread messages then the URL would be like
  			// https://chat.zulip.org/static/images/favicon/favicon-pms.png
  			if (favicons[0].indexOf('favicon-pms') > 0 && process.platform === 'darwin') {
  				// This api is only supported on macOS
  				app.dock.setBadge('●');
  				// bounce the dock
  				if (ConfigUtil.getConfigItem('dockBouncing')) {
  					app.dock.bounce();
  				}
  			}
  		});
  
  		this.$el.addEventListener('dom-ready', () => {
  			if (this.props.role === 'server') {
  				this.$el.classList.add('onload');
  			}
  			this.loading = false;
  			this.props.switchLoading(false, this.props.url);
  			this.show();
  
  			// Refocus text boxes after reload
  			// Remove when upstream issue https://github.com/electron/electron/issues/14474 is fixed
  			this.$el.blur();
  			this.$el.focus();
  		});
  
  		this.$el.addEventListener('did-fail-load', event => {
  			const { errorDescription } = event;
  			const hasConnectivityErr = (SystemUtil.connectivityERR.indexOf(errorDescription) >= 0);
  			if (hasConnectivityErr) {
  				console.error('error', errorDescription);
  				this.props.onNetworkError();
  			}
  		});
  
  		this.$el.addEventListener('did-start-loading', () => {
  			const isSettingPage = this.props.url.includes('renderer/preference.html');
  			if (!isSettingPage) {
  				this.props.switchLoading(true, this.props.url);
  			}
  			let userAgent = SystemUtil.getUserAgent();
  			if (!userAgent) {
  				SystemUtil.setUserAgent(this.$el.getUserAgent());
  				userAgent = SystemUtil.getUserAgent();
  			}
  			this.$el.setUserAgent(userAgent);
  		});
  
  		this.$el.addEventListener('did-stop-loading', () => {
  			this.props.switchLoading(false, this.props.url);
  		});
  	}
  
  	getBadgeCount(title) {
  		const messageCountInTitle = (/\(([0-9]+)\)/).exec(title);
  		return messageCountInTitle ? Number(messageCountInTitle[1]) : 0;
  	}
  
  	show() {
  		// Do not show WebView if another tab was selected and this tab should be in background.
  		if (!this.props.isActive()) {
  			return;
  		}
  
  		// To show or hide the loading indicator in the the active tab
  		if (this.loading) {
  			this.$webviewsContainer.remove('loaded');
  		} else {
  			this.$webviewsContainer.add('loaded');
  		}
  
  		this.$el.classList.remove('disabled');
  		this.$el.classList.add('active');
  		setTimeout(() => {
  			if (this.props.role === 'server') {
  				this.$el.classList.remove('onload');
  			}
  		}, 1000);
  		this.focus();
  		this.props.onTitleChange();
  		// Injecting preload css in webview to override some css rules
  		this.$el.insertCSS(fs.readFileSync(path.join(__dirname, '/../../css/preload.css'), 'utf8'));
  
  		// get customCSS again from config util to avoid warning user again
  		this.customCSS = ConfigUtil.getConfigItem('customCSS');
  		if (this.customCSS) {
  			if (!fs.existsSync(this.customCSS)) {
  				this.customCSS = null;
  				ConfigUtil.setConfigItem('customCSS', null);
  
  				const errMsg = 'The custom css previously set is deleted!';
  				dialog.showErrorBox('custom css file deleted!', errMsg);
  				return;
  			}
  
  			this.$el.insertCSS(fs.readFileSync(path.resolve(__dirname, this.customCSS), 'utf8'));
  		}
  	}
  
  	focus() {
  		// focus Webview and it's contents when Window regain focus.
  		const webContents = this.$el.getWebContents();
  		// HACK: webContents.isFocused() seems to be true even without the element
  		// being in focus. So, we check against `document.activeElement`.
  		if (webContents && this.$el !== document.activeElement) {
  			// HACK: Looks like blur needs to be called on the previously focused
  			// element to transfer focus correctly, in Electron v3.0.10
  			// See https://github.com/electron/electron/issues/15718
  			document.activeElement.blur();
  			this.$el.focus();
  			webContents.focus();
  		}
  	}
  
  	hide() {
  		this.$el.classList.add('disabled');
  		this.$el.classList.remove('active');
  	}
  
  	load() {
  		if (this.$el) {
  			this.show();
  		} else {
  			this.init();
  		}
  	}
  
  	zoomIn() {
  		this.zoomFactor += 0.1;
  		this.$el.setZoomFactor(this.zoomFactor);
  	}
  
  	zoomOut() {
  		this.zoomFactor -= 0.1;
  		this.$el.setZoomFactor(this.zoomFactor);
  	}
  
  	zoomActualSize() {
  		this.zoomFactor = 1.0;
  		this.$el.setZoomFactor(this.zoomFactor);
  	}
  
  	logOut() {
  		this.$el.executeJavaScript('logout()');
  	}
  
  	showShortcut() {
  		this.$el.executeJavaScript('shortcut()');
  	}
  
  	openDevTools() {
  		this.$el.openDevTools();
  	}
  
  	back() {
  		if (this.$el.canGoBack()) {
  			this.$el.goBack();
  			this.focus();
  		}
  	}
  
  	canGoBackButton() {
  		const $backButton = document.querySelector('#actions-container #back-action');
  		if (this.$el.canGoBack()) {
  			$backButton.classList.remove('disable');
  		} else {
  			$backButton.classList.add('disable');
  		}
  	}
  
  	forward() {
  		if (this.$el.canGoForward()) {
  			this.$el.goForward();
  		}
  	}
  
  	reload() {
  		this.hide();
  		// Shows the loading indicator till the webview is reloaded
  		this.$webviewsContainer.remove('loaded');
  		this.loading = true;
  		this.$el.reload();
  	}
  
  	send(...param) {
  		this.$el.send(...param);
  	}
  }
  
  module.exports = WebView;
  