text: /***
   * Created by lzq on 2018/11/02
   * Router.js
   */
  
  import $ from "jquery";
  import CtMobileFactory from "./CtMobile";
  import Constant from "./Constant";
  
  /**
   * 初始化
   * @access private
   */
  function initial() {
  	const self = this;
  
  	onHashchange = onHashchange.bind(this);
  
  	/***
     * 注册hashchange事件
     */
  	window.addEventListener("hashchange", onHashchange, false);
  
  	/***
     * 注册页面转场事件
     */
  	$(window.document).on("pageBeforeChange", function (e, params) {
  		self.setParameter(params);
  	});
  }
  
  /**
   * hashchange的回调函数
   * @access private
   * @callback
   */
  function onHashchange() {
  	// #page1_134567890232323?id=123_456
  	const hash = window.location.hash;
  	hashChange.call(this, hash);
  }
  
  /**
   * hashChange的处理
   * @access private
   * @param {string} hash - 哈希值
   * @param {Object} option - {
   *  reload :[true | false]
   * }
   */
  function hashChange(hash, option) {
  	const self = this;
  	/***
     * 转场的id(没有重复)
     * @type {string}
     */
  	let id = "";
  
  	if (hash) {
  		id = hash.indexOf("?") !== -1
  			? hash.substring(1, hash.indexOf("?"))
  			: hash.substring(1);
  
  		const index = id.lastIndexOf("_");
  		/***
       * 用户自定义的锚点跳转
       */
  		if (index === -1) {
  			return false;
  		} else {
  			const pageId = id.substring(0, index);
  			/***
         * 用户自定义的锚点跳转
         */
  			if (!window.document.querySelector("[ct-data-role='page'],#" + pageId)) {
  				return false;
  			}
  			self.ctmobile.fireEvent(window.document, "pageBeforeChange", [CtMobileFactory.getUrlParam(hash)]);
  		}
  	}
  	/***
     * 首页
     */
  	else {
  		self.ctmobile.fireEvent(window.document, "pageBeforeChange", [CtMobileFactory.getUrlParam(hash)]);
  		if (/*如果栈顶元素的pageId == 模板中第一页的id*/
  			self.ctmobile.getFirstPage().getPageId() === self.ctmobile.getFirstPageId()) {
  			// 说明是从模板的第一页进入主应用的
  			id = self.ctmobile.getFirstPage().getId();
  		}
  		else {
  			// 不是从模板的第一页进入主应用的
  			self.ctmobile.createPage(self.ctmobile.getId(self.ctmobile.getFirstPageId())).then((page) => {
  				page.start(Constant._SLIDEDURATION, () => {
  					self.removeFirstPage();
  				});
  			});
  			return;
  		}
  	}
  
  	//hash ? (hash.indexOf("?") != -1
  	//    ? id = hash.substring(1, hash.indexOf("?"))
  	//    : id = hash.substring(1))
  	//    : id = root.getFirstPage().getId();
  
  	/***
     * 新的页面
     */
  	const curPage = self.getPageById(id);
  	if (!curPage) {
  		self.ctmobile.createPage(id).then((page) => {
  			page.start(Constant._SLIDEDURATION, function () {
  				// 如果不改变浏览器历史且历史栈长度大于1
  				if (option && option.reload && self.getHistoryLength() > 1) {
  					const preHistoryIndex = self.getHistoryLength() - 2;
  					const preHistoryPage = self.getPageByIndex(preHistoryIndex);
  					if (preHistoryPage) {
  						preHistoryPage.finish(0, null, option);
  					}
  				}
  			});
  		});
  	}
  	/***
     * 回退
     */
  	else {
  		//  如果刷新的是栈顶的页面
  		if (id === self.getLastPage().getId()) {
  			return false;
  		} else {
  			// 依次出栈
  			const index = self.ctmobile.indexOfById(id);
  			for (let i = self.getHistoryLength() - 1; i > index; i--) {
  				if (i === index + 1) {
  					self.getPageByIndex(i).finish(Constant._SLIDEDURATION);
  				} else {
  					self.getPageByIndex(i).finish(0);
  				}
  			}
  		}
  	}
  }
  
  
  /**
   * history中是否有pageId开头的page对象
   * @access private
   * @param {string} pageId
   * @return {number}
   */
  function indexOfHistoryByPageId(pageId) {
  	if (pageId.indexOf("?") !== -1) {
  		pageId = pageId.substring(0, pageId.indexOf("?"));
  	}
  
  	let index = -1;
  	for (let i = 0, len = this.getHistoryLength(); i < len; i++) {
  		if (this.getPageByIndex(i).getPageId() === pageId) {
  			index = i;
  			break;
  		}
  	}
  	return index;
  }
  
  /**
   *  Router
   *  @class Router
   *  @classdesc 管理所有路由相关操作
   */
  class Router {
    /**
     * @constructor
     * @param {CtMobile} ctmobile
     */
    constructor(ctmobile) {
      Object.assign(this, {
        ctmobile,
        parameter: null,
        history: [],
      });
  
      initial.call(this);
    }
  
  
    /**
     * 页面跳转
     * @param {string} href (pageId = pageId + params) 如: page1?a=1&b=2;
     * @param {object} option {
     *    reload : [true | false]
     * }
     */
    startPage(href, option) {
      const self = this;
  
      let pageId = "", paramsQuery = "";
  
      // Ajax加载
      if (href.indexOf("#") !== 0) {
        let params = CtMobileFactory.getUrlParam(href);
        pageId = params.pageId;
  
        delete params.pageId;
        let paramsQueryArr = [];
        for (let p in params) {
          if (params.hasOwnProperty(p)) {
            paramsQueryArr.push(p + "=" + params[p]);
          }
        }
        paramsQuery = paramsQueryArr.join("&") ? ("?" + paramsQueryArr.join("&")) : "";
  
        // _templateDB中没有pageId的模板,则需要Ajax进行加载模板操作
        if (!(pageId in self.ctmobile.templateDB)) {
          $.ajax({
            dataType: "text",
            url: href,
            success(templateText) {
              self.ctmobile.templateDB[pageId] = CtMobileFactory.getPageTemplateStrByAjaxStr(templateText);
              // preload
              self.ctmobile.preload($(self.ctmobile.templateDB[pageId]));
              dispatcher();
            },
            error(error, status, thrown) {
  
            }
          });
        } else {
          dispatcher();
        }
      }
      // 本地锚点加载
      else {
        href = href.substring(1);
        if (href.indexOf("?") !== -1) {
          paramsQuery = href.substring(href.indexOf("?"));
          pageId = href.substring(0, href.indexOf("?"));
        } else {
          pageId = href;
        }
        dispatcher();
      }
  
      /***
       * 分派
       */
      function dispatcher() {
        /***
         * 获取page的模式
         */
        const mode = self.ctmobile.getTemplateConfig(pageId, "ct-data-mode");
        let hash;
        //if(/*单例*/mode === "single" || /*完全单例*/mode === "singleInstance" || /*带返回值的完全单例*/mode === "singleInstanceResult") {
        if (mode.toLowerCase().indexOf("single") !== -1) {
          const index = indexOfHistoryByPageId.call(self, pageId);
          if (/*_history中没有以pageId开头的page*/index === -1) {
            //1.用pageId生成真实的id转换锚点
            //if("singleInstance" === mode || "singleInstanceResult" === mode) {
            if (mode/*.toLowerCase()*/.indexOf("singleInstance") !== -1) {
              if (self.ctmobile.getSingleInstance(pageId)) {
                hash = self.ctmobile.getSingleInstance(pageId).getId();
              } else {
                hash = self.ctmobile.getId(pageId + paramsQuery);
              }
            } else {
              hash = self.ctmobile.getId(pageId + paramsQuery);
            }
  
            if (option && option.reload) {
              window.history.replaceState(null, "", "#" + hash);
              hashChange.call(self, "#" + hash, option);
            } else {
              window.location.hash = "#" + hash;
            }
          } else {
            if (/*如果page不是栈顶,依次出栈,调用finish*/
            self.ctmobile.getPageByIndex(index) !== self.getLastPage()
            ) {
              // 假如现在_history中的顺序是1,2,3,4,5,6，3是单例，现在要跳转到3,那么6,5,4所代表的page依次调用finish方法
              // history.go(找到3相对于当前页的阈值)
              self.go(-(self.getHistoryLength() - 1 - index));
            } else {
              self.ctmobile.fireEvent(self.getLastPage().getPageDOM(), "pageShow");
            }
          }
        } else if (/*多例*/mode === "standard" || mode === "result") {
          //1.用pageId生成真实的id转换锚点
          hash = self.ctmobile.getId(pageId + paramsQuery);
          if (option && option.reload) {
            window.history.replaceState(null, "", "#" + hash);
            hashChange.call(self, "#" + hash, option);
          } else {
            window.location.hash = "#" + hash;
          }
        }
      }
    }
  
    /**
     * 跳转到指定的历史
     * @param {number} index - 历史位置
     * 注释：当前的位置为0 index负值为回退，index正数为前进 都以1开始
     * 例如 -1 为当前页之前的页面,1为当前页之后的页面，0为刷新当前页面
     */
    go(index) {
      window.history.go(index);
    }
  
    /**
     * 返回
     */
    back() {
      this.go(-1);
    }
  
    /**
     * 设置转场参数
     * @param {Object} parameter
     */
    setParameter(parameter) {
      this.parameter = parameter;
    }
  
    /**
     * 获取转场的参数
     * @return {Object}
     */
    getParameter() {
      let parameter = Object.assign({}, this.parameter);
      if(parameter.pageId) {
        delete parameter.pageId;
      }
      return parameter;
    }
  
    /**
     * 根据ID获取page对象
     * @param {string} id
     * @return {*}
     */
    getPageById(id) {
      return this.history[this.ctmobile.indexOfById(id)];
    }
  
    /**
     * 根据索引获取page对象
     * @param {number} index
     * @returns {*}
     */
    getPageByIndex(index) {
      return this.history[index];
    }
  
    /**
     * 获取历史记录中的栈顶的元素
     * @returns {*}
     */
    getLastPage() {
      return this.history[this.history.length - 1];
    }
  
    /**
     * 获取历史栈长度
     * @return {number}
     */
    getHistoryLength() {
      return this.history.length;
    }
  
    /**
     * 添加页面的历史栈
     * @param {Page} page
     */
    addPage(page) {
      this.history.push(page);
    }
  
    /**
     * 删除历史栈中的第一个page
     */
    removeFirstPage() {
      this.history.shift();
    }
  
    /**
     * 删除历史栈中的最后一个页面
     */
    removeLastPage() {
      this.history.pop();
    }
  
    /**
     * 删除历史栈中指定的页面
     * @param {number} index
     */
    removePageByIndex(index) {
      this.history.splice(index, 1);
    }
  }
  
  export default Router;