Wiki.IModel.Object = Object.inherit(Wiki.Object, {
	i18n:function(key){return Wiki.I18N.get("model."+key);},
	getPrefix:function(type){
		return Wiki.Config.getComponentPrefix(type);
	},
	_getModelClass:function(type){return Wiki.Config.getComponentModelClassName(type);	},
	hasModelClass:function(type){return this._getModelClass(type).length>0;},
	newModelObject:function(type, pnode, idx, desc) {return new Wiki.Model[this._getModelClass(type)](pnode, idx, desc);},

	_genId:function(type, id){return this.getPrefix(type) +id;},
	getPureId:function(){return this._id.substring(this.getPrefix(this._type).length);},
	__setId:function(id){this._id = this._genId(this._type, id);},
	_init_Node:function(id,type){
		this._type = type;		
		this.__setId((id!=null)?id:IX.Utils.UUID.generate());
	}
});
Wiki.IModel.Model = Object.inherit(Wiki.IModel.Object, IX.IModel.Tree, {	
	__inheritAttrib:function(){},
	append:function(node){this._newChild(node);},
	cleanChilds:function(){this._subNodes=[];this._noc = 0;},

	find:function(id) {
		if (isEmpty(id)){return null;}
		var _isSame=function(xid) {
			var f = function(c) {return id.charAt(0)== c && xid.charAt(0) == c;};
			return f(this.getPrefix(this.__ITEM).charAt(0)) || xid==id;
		}.bind(this);
		return this.loopAll(null, function(acc, item, idx){
			return (acc || !item || isEmpty(item._id) || !_isSame(item._id))?acc:item;
		});
	},
	getItemId:function(){return this._isRoot?this._subNodes[0]._id.substring(1):this._root.getItemId();},
	getTitle:function(){return this._title.replaceAll("<","&lt;").replaceAll(">", "&gt;")+(this._type==this.__COMMENTS?("("+this._noc+")"):"");},
	
	getAllNode:function(){return this.loopAll([], IX.Utils.pushx);},
	getAllChild:function(){return this.loopDeep([], IX.Utils.pushx);},

	getAppxList:function() {
		var list = Wiki.Config.appendix[this._root._type];
		return IX.Utils.loop([].concat(list[0], list[1], list[2]), [], function(acc, item){return IX.Utils.pushx(acc, this["__"+ item]);}.bind(this));
	},
	hasAppx:function(type) {return IX.Utils.loop(this.getAppxList(), false, function(acc, item) {return acc || (type==item);});},

	_isType:function(type){return this._isRoot?(this._type==type):this._root._isType(type);},	
	isWiki:function(){return this._isType(101);},
	isKFolder:function(){return this._isType(102);},
	isRFolder:function(){return this._isType(104);},
	isImgFolder:function(){return this._isType(105);},
	isFolder:function(){return this.isKFolder() || this.isRFolder() || this.isImgFolder()||this.isBookFolder();},
	isImage:function(){return this._isType(103);},
	isBookFolder:function(){return this._isType(107);},
	isBook:function(){return this._isType(106)||this._isType(107);},

	isNew:function(){return this._isRoot?this._isNew:this._root.isNew();},
	isNode:function(){return this._type<2;},
	isItem:function(){return this._type==0;},
	isSection:function(){return this._type==1;}
});
Wiki.IModel.Node = Object.inherit(Wiki.IModel.Model, {
	_getDefaultI18N:function(idx){
		var tname = {0:"item", 1:(this._tidx=="1"?"firstSection":"newSection"), 5:"comment", 90:"item"}[this._type];
		return this.i18n(tname +"Temp." + idx);
	},
	save:function(title, content){
		var param = [title?title.trim().replaceAll("<", "&lt;").replace(/\$/g, "&#36"):"", content.stripScripts().stripFormTag().replaceAll("&#x000D;", "\n").replaceAll("&apos;", "'").replace(/\$/g, "&#36")];
		if (param[0]==this._title && this._content==param[1]){return false;}
		this._title = param[0]?param[0]:(this._type<2?this._getDefaultI18N(0):"");
		this._content=param[1]?param[1]:"";
		return true;
	},
	_saveNew:function(desc, stx){
		var nd = [];
		for(var i=0; i<2; i+=1){
			nd[i] = (this._type==this.__UNKNOWN)?"":getFromArray(desc, stx*1 +i, this._getDefaultI18N(i));
		}
		return this.save(nd[0],nd[1]);
	},
	getTidxForce:function(postfix){return this._tidx+(postfix?postfix:"");},
	getContent:function(){return this._content;}
});
Wiki.IModel.Comment = {
	__Cmt_VIRTUAL_FUN: ["__ifLoaded"],

	__loadItemList:function(){this._root.callServer("loadcmt", [this._expand_stat]);},
	_expand:function(es){
		this.__doExpand(es);
		if (!this.__ifLoaded()){this.__loadItemList(); return false;}
		return true;
	},
	collapseAll:function(){this.__doExpand(-1); return true;},
	collapse:function(){return this.__doExpand(0)},
	expand:function(){return this._expand(1);},
	expandAll:function(){return this._expand(2);},

	post:function(title, content){
		var comment =this.newModelObject(this.__COMMENT, this, this._noc, null);
		this.append(comment);
		comment.save(title, content);
		return comment;
	}
};
Wiki.IModel.KItem = Object.inherit(Wiki.IModel.Model, {
	update:function(desc){
		this._title = getFromObject(desc, "title","");
		IX.Utils.each(desc, 0, function(acc, pval, pname, idx){
			if (pname!="id" && pname !="title"){
				this["_$"+ pname] = pval;
			}
		}.bind(this));
	},
	collapse:function(){return this.__doExpand(0)},
	expand:function(){return this.__doExpand(1);},
	getProps:function(name){
		if (name=="id"){return this._id.substring(this.getPrefix(this._type).length);}	
		if (name=="title"){return this._title;}
		var rname = "_$"+name;
		return (rname in this)?this[rname]:null;
	},
	getIdx:function(){return this._idx;},
	_initItem:function(pnode, idx, desc, itype) {
		this._init_Node((pnode._type==this.__KITEMS?"":(pnode.getPureId()+"/")) + getFromObject(desc, "id",null) , itype);
		this._init_Tree(pnode, idx, 0, null);
		this.update(desc);
	}
});
Wiki.IModel.Appendix = Object.inherit(Wiki.IModel.Model,{
	__Appendix_VIRTUAL_FUN: ["_load", "_getAppxType"],

	__getElem:function(aid){return [aid, this._appx[aid][0],this._appx[aid][1]];},
	__setElem:function(acc, item){acc[item[0]]=[item[1], item[2]];return acc;},
	_getAll:function(t) {// t: "id"/"all"
		return IX.Utils.each(this._appx, [], function(acc, item, pname){
			return item==null?acc:IX.Utils.pushx(acc, t=="id"?pname:this.__getElem(pname));
		}.bind(this));
	},
	getContent:function(){return "";},
	_load:function(desc){this._appx = IX.Utils.loop(desc, {}, this.__setElem);},
	load:function(desc){this._load(desc);},
	getAll:function(){return this._getAll("all");},
	initialize:function(root, idx, desc) {
		var t= this._getAppxType();
		this._init_Node("", t);
		this._init_Tree(root, idx, 0, null);
		this._title = this.i18n("title."+ t);
		this._load(desc);
	}
});
Wiki.IModel.ItemList = Object.inherit(Wiki.IModel.Appendix, IX.IModel.MutliPage, {
	__ifLoaded:function(){ return this.ifPageLoaded(function(acc, item){return acc;});},
	__getItemList:function(){return this._subNodes;},

	getColumns:function(){return this._columns;},
	__updItem:function(kitemDesc, itype) {
		var  pid = getFromObject(kitemDesc, "pid", null);
		var idx = getFromObject(kitemDesc, "idx", -1) * 1;
		var pnode = pid==null?this:this.find(this._id + pid);
		var  item = this.newModelObject(itype, pnode, idx == -1?this._noc:idx, kitemDesc);
		if(idx ==-1) {pnode.append(item);}
		else {
			pnode._subNodes[idx] = item;
			pnode._noc = Math.max(pnode._noc, idx+1); 
		}
		item._isSelf = getFromObject(kitemDesc, "isSelf", 0)*1;
	},
	__updList:function(ifCover, noc, curPidx, noipp) {
		if (ifCover){
			this._setCurPageIdx(curPidx);
			this._setNoipp(noipp);
		} else {
			this._init_MultiPage(noc, curPidx, noipp);
			this._subNodes=[];
			//this._subNodes.length = this._noc;
		}
	},
	__updColumns:function(desc) {
		var arr =  getFromArray(desc, 4, [[]])[0];
		this._columns = {orderBy: getFromArray(arr, 1, "id"), order: getFromArray(arr, 2, "desc"),list: getFromArray(arr, 3, [])};
	}
});
Wiki.IModel.Section = Object.inherit(Wiki.IModel.Node, {
	getLastNode:function(){
		var node = this;
		while(node._noc>0){node = node._subNodes[node._noc-1];}
		return node;
	},
	getPrevSeqNode:function(){
		if(this._level==0||this._tidx=="1" ){return null;}
		var idx = this._tidx.split(".").pop()-2;
		var node = this._parent;
		return (idx>=0)?node._subNodes[idx].getLastNode():node;
	},
	getNextSeqNode:function(){
		var fun = function(node, idx){return node._noc>idx?node._subNodes[idx]:null;};
		var node = fun(this, 0);
		return (node || this._level==0)?node:IX.Utils.loopDsc(this._tidx.split("."), [this, null], function(acc, item){
			return acc[1]!=null?acc:[acc[0]._parent, fun(acc[0]._parent, item)];
		})[1];
	},

	getVersion:function(){return this._version;},
	setVersion:function(ver){this._version =ver;},

	getEdTidx:function(dtype) {
		var tidx= this.getTidxForce();
		var tidxArr = isEmpty(tidx)?[]:tidx.split(".");
		switch(dtype*1){
		case 0:tidxArr.push(this._noc*1+1); break;
		case 3: tidxArr.pop();
		case 2: tidxArr.push(tidxArr.pop()*1+1);break;
		case -2:tidxArr.push(1);break;
		default:break;
		}
		return tidxArr.join(".");
	},
	// More to be done for version;
	saveSection :function(htm, dtype) {
		var cvt = new Wiki.SDEPConverter();
		return this.dynSave(cvt.parseHTML(htm), dtype);
	},
	dynSave:function(datalist, dtype){ //datalist:[[level, title, description],...]; dtype: 0~3, -1, -2 ,-3
		if(this.isItem() && dtype==-2){
			this.cleanChilds();
			var item=(datalist&& datalist.length>0)?datalist[0]:null;
			var rid = null;
			if(item && item[0]==-1){
				rid= this.save(this._title, item[2])?this._id:null;
				datalist.shift();
			} else {
				rid= this.save(this._title, "")?this._id:null;
			}
			return ((rid!=null)?[rid]:[]).concat(this._root.updateSections(null, datalist));
		}

		var pnode = this;
		if (dtype==2 || dtype==0){pnode = pnode.getLastNode();}
		else if (dtype!=-2){pnode = pnode.getPrevSeqNode();}
		if(pnode !=null){
			var item = datalist[0];
			if (item[0]==-1){item[0] = this.getEdTidx(dtype).split(".").length;}
		}
		if (dtype==-2 && dtype==-3) {this.loop(0, function(acc, item){item.suicide();});}
		var newIdlist = this._root.updateSections(pnode, datalist);

		if (dtype==3 ) {
			pnode = this.getRoot().find(newIdlist[newIdlist.length-1]);
			pnode = pnode.getAncestor(this._level-1);
			var ppnode = this._parent;
			var idx = this._idx;
			while(ppnode._noc>idx){
				ppnode._subNodes[idx]._move(pnode, 0);
			}
		}
		if (dtype ==-1) {
			pnode = this.getPrevSeqNode();
			if (pnode!=null){pnode = pnode.getAncestor(this._level);}
			this.loop(0, function(acc, item){item._move(pnode, 0);});
		}
		if (dtype==-1 || dtype==-3) {this.suicide();}
		return newIdlist;
	},

	_init_Section:function(pnode, idx, desc, type){
		this._init_Node(getFromArray(desc, 1, null), type);
		this._init_Tree(pnode, idx, 0, null);
		this._saveNew(desc,2);
		// version: default is -1: 
		// as editing all secitons, all seciton will be "new" secitons and the version is set to -1;
		this._version = getFromArray(desc, 4, "-1");
	}
});

// desc: [id, title, content, version]
Wiki.Model.Section=IX.Class.create();
Wiki.Model.Section.prototype = Object.inherit(Wiki.IModel.Section, {
	__genIdx:function(idx){
		idx =idx?idx:0;
		this._tidx = (this._level<2?"":(this._parent._tidx +".")) + (idx*1+1);
		return idx;
	},
	getAncestor:function(level){
		if (level>this._level || level<0){return null;}
		var node = this;
		while(level<node._level){node = node._parent;}
		return node;
	},
	getTidx:function(postfix){return Wiki.Config.ifShowTidx?this.getTidxForce(postfix):"";},
	
	suicide:function(){this._parent._delChild(this._idx);},
	move:function(dst, dtype){this._move(dst,dtype);},
	initialize:function(pnode, idx, desc){this._init_Section(pnode, idx, desc, this.__SECTION);}
});
// desc: [id, title, content, version, doctype, topic, exttopic] //, path]
Wiki.Model.Item=IX.Class.create();
Wiki.Model.Item.prototype = Object.inherit(Wiki.IModel.Section, {
	__genIdx:function(idx){this._tidx = "";return idx?idx:0;},
	_hasTags:function(){return this.hasAppx(this.__TAGS);},
	_getTags:function(){return this._root.getAppx(this.__TAGS);},
	getTags:function(){return this._hasTags()?this._getTags()._getAll("id"):[];},
	saveTags:function(ntags){
		if (!this._hasTags()){return false;}
		var realTags = IX.Utils.loop(ntags.split(","), [], function(acc, item){
			var tag= item.trim();
			if (tag.length>0 && !IX.Utils.isFound(tag, acc)){acc.push(tag);}
			return acc;
		});
		if (IX.Utils.isSameArray(this.getTags(), realTags)){return false;}
		this._getTags().load(IX.Utils.loop(realTags, [], function(acc, item){
			return IX.Utils.pushx(acc, [item, []]);
		}));
		return true;
	},
	getTidx:function(){return "";},
	getTidxForce:function(){return "";},
	getPath:function(){return this._path;},

	getTopic:function(){return this._topic;},
	saveTopic:function(topic){
		if (this._topic== topic){return false;}
		this._topic = topic;
		return true;
	},
	getExtTopic:function(){return this._exttopic;},
	loopExtTopics:function(acc, fun) {
		var exttopic = this._exttopic;
		return IX.Utils.loop((exttopic && exttopic.length>0)?exttopic[0]:[],acc, fun);
	},
	removeTopics:function(topics){
		this._exttopic = [this.loopExtTopics([], function(acc, item, idx) {
			if (topics && topics.length>0 && idx == topics[0][0]) {
				topics.shift();
			} else {
				acc.push(item);
			}
			return acc;
		})];
		this._root.callServer("saveTopic");
	},
	updateTopic:function(idx, topic, sectionTitle) {
		var  item = ["" + topic, ""+ sectionTitle];
		var extTopics = this._exttopic;
		if (!extTopics || extTopics.length==0){
			extTopics = [item];
		} else {
			extTopics = extTopics[0];
			if( IX.Utils.loop(extTopics, false, function(acc, item1, idx1){
				return (idx1!=idx && item[0]==item1[0])?true:acc;
			})){
				alert("The typed topic identifier existed. Ignore it."); 
				return false;
			}
			if (idx ==-1  || idx >=extTopics.length){
				extTopics.push(item);
			}else {
				var nitem = extTopics[idx];
				if (item[0]==nitem[0] && item[1]==nitem[1]){
					return false;
				}
				extTopics[idx]=item;
			}
		}
		this._exttopic = [extTopics];
		this._root.callServer("saveTopic");
		return true;
	},
	/* dropped!
	saveExtTopic:function(topic){
		var realTopics = IX.Utils.loop(topic.split(","), [], function(acc, item){
			var tag= item.trim();
			if (tag.length>0 && !IX.Utils.isFound(tag, acc)){acc.push(tag);}
			return acc;
		});
		if (IX.Utils.isSameArray(this._exttopic.split(","), realTopics)){return false;}		
		this._exttopic= realTopics.join(","); 
		return true;
	},*/
	getTOC:function(){
		return this.loopAll([], function(acc, item){
			acc.push([item.getId(), item.getTidxForce(), item.getTitle()]);
			return acc;
		});
	},

	initialize:function(root, idx, desc){
		this._init_Section(root, idx, desc, this.__ITEM);
		this._path = "";
		var title = ""+ this._title;
		var idx = title.lastIndexOf('\\');
		if (this.isFolder() && idx>=0) {
			this._title = title.substring(idx+1);
			this._path =  title.substring(0, idx+1);
		}
		this._topic = getFromArray(desc, 6, "");
		this._exttopic = getFromArray(desc, 7, "");
	}
});
// desc: [id, title, content, [posterId, posterName], postTime]
Wiki.Model.Comment = IX.Class.create();
Wiki.Model.Comment.prototype = Object.inherit(Wiki.IModel.Node, Wiki.IModel.Comment,{
	__genIdx:function(idx){
		idx =idx?idx:0;
		this._tidx =this._level==1?(idx*1+1):"";
		return idx;
	},
	__ifLoaded:function() {return this[(this._expand_stat==2?"loopDeep":"loop")](true, function(acc, item){return acc && item;});},
	_init_Comment:function(desc){
		this._init_Node(getFromArray(desc, 1, null), this.__COMMENT);
		this._saveNew(desc, 2);
		var poster = getFromArray(desc, 4, [wiki_getCurUid(), wiki_getCurUname()]);
		this._posterId = poster[0] ;
		this._postName = poster[1];
		this._postDate = getFromArray(desc, 5, new Date());
	},

	resetId:function(id){this.__setId(id);},
	update:function(desc){this._init_Comment(desc);},

	getTidx:function(postfix){return this.getTidxForce(postfix);},
	getPoster:function(){return this._postName;},
	getPosterId:function(){return this._posterId;},
	canEdit:function(){return this._posterId==wiki_getCurUid() && !Wiki.Config.readonly; },
	getDate:function(){return this._postDate;},
	initialize:function(pnode, idx, desc) {
		this._init_Comment(desc);
		this._init_Tree(pnode, idx, 0, null);
	}
});
// desc: [[ id, title, type],...]
Wiki.Model.Linked = IX.Class.create();
Wiki.Model.Linked.prototype = Object.inherit(Wiki.IModel.Appendix, {_getAppxType:function(){return this.__LINKS;}});

//desc:[[groupId, editable, name, [[id, title, type], .]], ... ]
Wiki.Model.QuickLinks = IX.Class.create();
Wiki.Model.QuickLinks.prototype = Object.inherit(Wiki.IModel.Appendix, {
	_getAppxType:function(){return this.__QUICKLINKS;},
	setExpanded:function(gid, stat){if (gid in this._appx){this._appx[gid][3]=stat;}},
	getGroupByTitle:function(title){return IX.Utils.each(this._appx, [], function(acc, item, pname){
		if (item==null ||acc.length>0){return acc;}
		var grp= this.__getElem(pname);
		return grp[1]==title?grp:acc;
	}.bind(this));},
	__getElem:function(aid){var itm =  this._appx[aid];return [].concat(aid,itm);},
	_load:function(desc){
		var appx = "_appx" in this?this._appx:{};
		this._appx = IX.Utils.loop(desc, {}, function(acc, item){
			var gid = item.shift();
			item[0] = item[0]!="false";
			item.push(gid in appx?appx[gid][3]:(Wiki.Config.ifQuickLinkGroupExpaned?1:0));
			acc[gid?gid:"default"]=[].concat(item);
			return acc;
		}.bind(this));
	}
});

// desc: [[id, title, url], ...]
Wiki.Model.Attachment = IX.Class.create();
Wiki.Model.Attachment.prototype= Object.inherit(Wiki.IModel.Appendix, {_getAppxType:function(){return this.__ATTACHMENTS;}});

// desc: [[tagName, [[id, title, type],...]], ...]
Wiki.Model.Tag = IX.Class.create();
Wiki.Model.Tag.prototype = Object.inherit(Wiki.IModel.Appendix, {
	_getAppxType:function(){return this.__TAGS;},
	__getElem:function(aid){return [aid, this._appx[aid]];},
	__setElem:function(acc, item){acc[item[0]]=item[1];return acc;}
});
// desc: [total, noipp, curp]
Wiki.Model.Comments = IX.Class.create();
Wiki.Model.Comments.prototype = Object.inherit(Wiki.IModel.Appendix, Wiki.IModel.Comment, IX.IModel.MutliPage, {
	_getAppxType:function(){return this.__COMMENTS;},
	__ifLoaded:function(){return this.ifPageLoaded(function(acc, item, i) {return acc && item.__ifLoaded();});},
	__getItemList:function(){return this._subNodes;},
	_load:function(desc){
		this._init_MultiPage(getFromArray(desc, 1, 0), getFromArray(desc, 3, 0), getFromArray(desc, 2, 10));
		this._subNodes.length = this._noc;
		this.__doExpand(1);
	}
});
Wiki.Model.Unknown = IX.Class.create();
Wiki.Model.Unknown.prototype = Object.inherit(Wiki.IModel.Node, {
	_reset:function(title, content){
		this.save(title, content);
		this._tidx = "";
	},
	reset:function(){ this._reset("","");},
	setTidxForce:function(tidx){this._tidx=tidx;},
	initialize:function() {
		this._init_Node("", this.__UNKNOWN);
		this.reset();
	}
});

// desc: url
Wiki.Model.KImage = IX.Class.create();
Wiki.Model.KImage.prototype = Object.inherit(Wiki.IModel.Appendix, {
	_getAppxType:function(){return this.__KIMAGE;},
	_load:function(desc){this._appx = desc;},
	getUrl:function(){return this._appx;},
	getAlt:function(){return this._root.find("root").getTitle();}
});

// desc: {id:"id", title:"title name", type:"1?", pid:, idx:,  ...}
Wiki.Model.KItem = IX.Class.create();
Wiki.Model.KItem.prototype = Object.inherit(Wiki.IModel.KItem, {
	initialize:function(pnode, idx, desc){
		this._initItem(pnode, idx, desc, this.__KITEM);
	}
});

// desc: [total, noipp, curp, columns, incChild, imgType, reqType, specType, refType]
Wiki.Model.KItems = IX.Class.create();
Wiki.Model.KItems.prototype = Object.inherit(Wiki.IModel.ItemList, {
	__loadItemList:function(){this._root.callServer("loadki", [this._incChild]);},
	_getAppxType:function(){return this.__KITEMS;},

	getActionType:function() {return this._actionType;},
	getViewParams:function(){
		switch(this._root._type){
		case 104:return [["req", this._reqType],["spec", this._specType],["ref", this._refType]];
		case 105:return [["img",this._imgType]];
		case 102:		
		default: return null;
		}
	},
	ifIncludeChild:function(){return this._incChild;},
	setIncludeChild:function(incChild){
		this._incChild = incChild;
		this._curPIdx= 0;
		this.__loadItemList();
	},
	setViewParam:function(t, v){
		var maxO= {req:3, spec:3, ref:2, img:2};
		var value = v%(maxO[t]);
		this["_"+t +"Type"] = value;
		if (this.isRFolder() && t!="ref" && value==0) {
			var type= (t=="req")?"_specType":"_reqType";
			if (this[type]==0){this[type] = 1;}
		}
		this._root.callServer("loadki");
	},
	resetViewParam:function(type){this.setViewParam(type,this["_"+type +"Type"]*1+1);},
	link2Topic:function(idList){
		this._root.callServer("linkki", idList);
	},
	updateSelfItemTitle:function() {
		for (var idx in this._subNodes) {
			var item = this._subNodes[idx];
			if (item && item._isSelf==1) {
				item._title = this._root.find("root")._title;
				return item;
			}
		}
		return null;
	},
	_updKItem:function(kitemDesc) {this.__updItem(kitemDesc, this.__KITEM);},
	_load:function(desc){
		var incChild = getFromArray(desc, 5, "false")=="true";
		var noc = getFromArray(desc, 1, 0);
		
		var ifCover = ("_incChild" in  this && this._incChild==incChild && noc == this._noc);
		this.__updList(ifCover , noc, getFromArray(desc, 3, 0),  getFromArray(desc, 2, 10));
		if (!ifCover) {
			this._incChild = incChild;
		}
		this.__updColumns(desc);

		if (this.isImgFolder()){
			this._imgType = getFromArray(desc, 6, 0)%2;
		} else if (this.isRFolder()){
			this._reqType = getFromArray(desc, 7, 1)%3 ;
			this._specType = getFromArray(desc, 8, 1)%3;
			this._refType = getFromArray(desc, 9, 0)%2 ;
		}
		this._actionType = getFromArray(desc, 10, "wiki");
		this._cond = getFromArray(desc, 11, "");
		this.__doExpand(2);
	}
});

// desc: {id:"id", title:"title name", type:"1?", pid:, idx:,  ...}
Wiki.Model.SItem = IX.Class.create();
Wiki.Model.SItem.prototype = Object.inherit(Wiki.IModel.KItem, {
	initialize:function(pnode, idx, desc){this._initItem(pnode, idx, desc, this.__SITEM);}
});

// desc: [total, noipp, curp, columns, scond]
Wiki.Model.SItems = IX.Class.create();
Wiki.Model.SItems.prototype = Object.inherit(Wiki.IModel.ItemList, {
	__loadItemList:function(){this._root.callServer("loadsi");},
	_getAppxType:function(){return this.__SITEMS;},

	getCondition:function(){return this._scond;},
	setCondition:function(cond){
		this._cond = cond;
		this.__loadItemList();
	},
	_updSItem:function(sitemDesc) {this.__updItem(sitemDesc, this.__SITEM);},
	link2Topic:function(idList){
		this._root.callServer("linksi", idList);
	},
	_load:function(desc){
		var noc = getFromArray(desc, 1, 0);
		var cond = getFromArray(desc, 5, "");

		var ifCover = (this._cond==cond && noc==this._noc);
		this.__updList(ifCover , noc, getFromArray(desc, 3, 0),  getFromArray(desc, 2, 10));
		if (!ifCover) {this._cond = cond;}
		this.__updColumns(desc);
		this.__doExpand(2);
	}
});

Wiki.Model.Page = IX.Class.create();
Wiki.Model.Page.prototype = Object.inherit(Wiki.IModel.Model, Wiki.SDEP, {
	initialize:function(pageXml){
		var xmlDoc = IX.Xml.parser(pageXml);
		this.reset(xmlDoc.firstChild);
	},
	getAppx:function(type) {return this.hasAppx(type)?this.find(this._genId(type, "")):null;},
	_createSection:function(){
		var item = 	this.find("root");
		var node = this.newModelObject(this.__SECTION, item, item._noc, null);
		node.view_stat = true;
		item.append(node);	
		return node;
	},
	createSection:function(title, content){
		var node = this._createSection();
		node.save(title, content);
		return node;
	},
	updateSections:function(prevSection, nodelist){return IX.Utils.loop(nodelist, [prevSection, []], function(acc, item){
		if (isEmpty(item[1])&& isEmpty(item[2])){return acc;}
		var node = this.createSection(item[1], item[2]);
		acc[1].push(node.getId());
		if(acc[0] && ("getAncestor" in acc[0])){
			var param = [2, acc[0].getAncestor(item[0])];
			if (param[1]==null){param = (acc[0]._noc>0)?[1, acc[0]._subNodes[0]]:[0, acc[0]];}
			node.move(param[1], param[0]);
		} else {
			var xitem = this.find("root");
			if (xitem._noc >0){node.move(xitem._subNodes[0], 1);}
		}
		acc[0] = node;
		return acc;
	}.bind(this))[1];}
},{	// handler for response from server;
	__MTAGS:  {0:"wiki", 1:"sections", 2:"lkws", 3:"comments", 4:"attachs", 6:"rkws",8:"qlkws", 9:"itemlist",11:"img", 13:"search"},
	__PTAGS:{1:"sections", 5:"comments"},
	__SUBTAGS:{1:"section", 5:"comment"},
	__IDSTAGS:{1:"section_ids",2:"lkw_ids",  4:"attach_ids", 5:"comment_ids"},

	__cvtDescArr:function(node, type) {return this.__cvtToArray(this.__$first(node, this.__PTAGS[type]), this.__SUBTAGS[type]);},
	__cvtKItemsObj:function(node){return this.__cvtToObject(node, this.__MTAGS[this.__KITEMS]);},
	__cvtSItemsObj:function(node){return this.__cvtToObject(node, this.__MTAGS[this.__SITEMS]);},
	__cvtAppxToDesc:function(appxNode, type){
		var desc=this.__cvtToElem(appxNode,  this.__MTAGS[type]);
		return (type!=this.__COMMENTS&& type!=this.__KITEMS && type!=this.__SITEMS && desc.length>0)?desc[0]:desc;
	},
	__cvtToAppxDesc:function(node, type){
		return this.__cvtAppxToDesc(this.__$first(node,  this.__MTAGS[type]), type);
	},
	__genChilds:function(node, type){
		var isSec = type==this.__SECTION;	
		var offsetArr = isSec?5:6;
		var descArr =  IX.Utils.sort(this.__cvtDescArr(node,type), 0, offsetArr-1, offsetArr);
		while(descArr.length>0) {
			//alert(descArr.length);
			var snode = descArr.shift();
			var pnodeid = snode[offsetArr-1];
			pnodeid= pnodeid.length==0?(isSec?"root":""):pnodeid;
			var pnode = this.find(this._genId(type,pnodeid!="0"?pnodeid:""));
			if (!pnode){continue;}
			var idx = isSec?pnode._noc:snode[offsetArr];
			var xnode = this.newModelObject(type, pnode, idx, snode);
			if(isSec) {pnode.append(xnode);} 
			else {
				pnode._subNodes[idx] = xnode;
				if(pnode._level>0){pnode._noc = pnode._subNodes.length;}
			}
		}		
	},
	__updIds:function(node, type){
		var idList = this.__$text(node,this.__IDSTAGS[type]);
		return (idList=="")?[]:IX.Utils.loop(idList.split(","), [], function(acc, item) {
			var ids = item.split("=");
			if (ids.length==2){
				ids = [this._genId(type,  ids[0]),this._genId(type,  ids[1])];
				var m = this.find(ids[1]);
				if(m){m._id = ids[0];acc.push(ids.join("="));}
			}
			return acc;
		}.bind(this));
	},
	__updChilds:function(node, type){return IX.Utils.loop(this.__cvtDescArr(node,type), false, function(acc, item){
		var cnode = this.find(this._genId(type,item[0]));
		if (cnode){
			cnode.save(item[1], item[2]);
			if(item[3]){cnode.setVersion(item[3]);}
		}
		return true;
	}.bind(this));},
	__genKItemDesc:function(item){
		if (!item || !("_childs" in item) || !("lkw" in item._childs) || item._childs.lkw.length==0){return null;}
		var obj =item._childs.lkw[0];
		if (!obj){return null;}
		var attrs = Object.inherit({pid:"", idx:-1},getFromObject(item, "_attrs",{}),getFromObject(obj, "_attrs",{}));
		var desc = {id:attrs.id, isSelf:attrs.isSelf, type:attrs.type, pid:attrs.pid, idx:attrs.idx, title:obj._childs._cdata};
		obj = getFromObject(item._childs, "img",null);
		if (obj && obj.length>0){desc.img = obj[0]._childs._text;}
		return IX.Utils.loop(item._childs.param, desc, function(xacc, xitem){
			xacc[xitem._attrs.name] = Object.inherit(xitem._attrs, xitem._childs);
			return xacc;
		});
	},
	__genKItemList:function(node){
		var kilist = this.__cvtKItemsObj(node);
		if(!kilist){return;}
		var kitems = this.getAppx(this.__KITEMS);
		var attrs =  kilist._attrs;
		var startIdx = attrs.ifAll?0:(attrs.curp * attrs.noipp);
		IX.Utils.loop(kilist._childs.item, 0, function(acc, item, idx){
			var desc = this.__genKItemDesc(item);
			if(desc){kitems._updKItem(desc);}
		}.bind(this));
	},
	__genSItemList:function(node){
		var silist = this.__cvtSItemsObj(node);
		if(!silist){return;}
		var sitems = this.getAppx(this.__SITEMS);
		var attrs =  silist._attrs;
		var startIdx = attrs.ifAll?0:(attrs.curp * attrs.noipp);
		IX.Utils.loop(silist._childs.item, 0, function(acc, item, idx){
			var desc = this.__genKItemDesc(item);
			if(desc){sitems._updSItem(desc);}
		}.bind(this));
	},
	__updKItemList:function(node){
		var desc = this.__cvtToAppxDesc(node, this.__KITEMS);
		if (desc.length==0) {return false;}
		this.getAppx(this.__KITEMS).load(desc);
		this.__genKItemList(node);
		return true;
	},
	__updSItemList:function(node){
		var desc = this.__cvtToAppxDesc(node, this.__SITEMS);
		if (desc.length==0) {return false;}
		this.getAppx(this.__SITEMS).load(desc);
		this.__genSItemList(node);
		return true;
	},
	_getKilistDesc:function(node) {
		var kilist = this.__cvtKItemsObj(node);
		if (kilist ==null) {return null;}
		var kitems = kilist._childs.item;
		if (!kitems || kitems.length==0) {return null;}
		return this.__genKItemDesc(kitems[0]);
	},
	loaditem:function(wikiXml){ // update single item
		var desc = this._getKilistDesc(wikiXml);
		if(desc==null){return [];}
		
		var kitems = this.getAppx(this.__KITEMS);
		var kidx = kitems.loopPage(-1, function(acc, item, idx) {
			if(acc==-1 && item.getProps("id") == desc.id) {
				item.update(desc);
				acc = idx;
			}
			return acc;
		});
		if (kidx==-1) {
			kitems._updKItem(desc);
			return [desc.id];
		}
		return [];
	},

	__getType:function(docType){
		switch(docType){
		case "kfolder":return 102;
		case "rfolder":return 104;
		case "ifolder":return 105;
		case "image":return 103;
		case "bitem":return 106;
		case "bfolder":return 107;
		case "titem": return 108;
		//case "item": return 100;
		//case "wiki":
		//case "template":
		//case "new":
		default:return 101;
		}
	},
	__getIfNew:function(docType){
		switch(docType){
		case "template":
		case "new": return true;
		//case "item": 
		case "folder":
		case "image":		
		//case "wiki":
		default:return false;
		}
	},	
	_setProps:function(arr){
		this._init_Node("", this.__getType(arr[4]));
//		if (this._type==106 || this._type==107){
//			Wiki.Config.readonly = true;
//		}
		this._init_Tree(null, 0, 0, null);
		this._title ="Page";
		this._isNew =this.__getIfNew(arr[4]);
		this._subNodes.push(this.newModelObject(this.__ITEM, this, 0, arr));
	},
	_getAppendixList:function(apxArr) {return IX.Utils.loop(this.getAppxList(), [], function(acc, item){
		if (item in apxArr){acc.push(apxArr[item]);} 
		return acc;
	});},
	reset:function(wikiXml){
		var arr =  this.__cvtToElem(wikiXml, this.__MTAGS[this.__ITEM]);
		var content = arr[2];
		arr[2] = "";
		this._setProps(arr);
		var idx = 1;
		IX.Utils.loop(this.getAppxList(), 0, function(acc, item){
			if (this.hasModelClass(item)) {
				this._subNodes.push(this.newModelObject(item, this, idx, this.__cvtToAppxDesc(wikiXml, item)));
				idx += 1;
			}
		}.bind(this));
		this._subNodes.push(this.newModelObject(this.__UNKNOWN, this));
		this._noc = this._subNodes.length;
		var wItem = this.find("root");
		wItem.saveSection(content, -2);
		if(!wItem.hasChild()) {this.__genChilds(wikiXml, this.__SECTION);}
		if (this.getAppx(this.__COMMENTS)){this.__genChilds(wikiXml, this.__COMMENT);}
		if (this.getAppx(this.__KITEMS)){this.__genKItemList(wikiXml);}
		if (this.getAppx(this.__SITEMS)){this.__genSItemList(wikiXml);}
		if (this._isNew && !wItem.hasChild()){this._createSection();}
	},
	_updatePage:function(wikiXml){
		var item = this.find("root");
		var ifRoot = false;
		var title = this.__$first(wikiXml, "title");
		if (title!=null){
			var  txt = this.__$$cdata(title);
			var idx = txt.lastIndexOf('\\');
			if (this.isFolder() && idx>=0) {txt =  txt.substring(idx+1);}
			ifRoot =item.save(txt.replaceAll("&amp;", "&"), item.getContent());
		}
		title = this.__$first(wikiXml, "topic");
		if (title!=null){
			var  txt = this.__$$cdata(title);
			ifRoot =item.saveTopic(txt) ;
		}
		title = this.__$first(wikiXml, "exttopic");
		if (title!=null){
			var  txt = this.__$$cdata(title);
			ifRoot = item.saveExtTopic(txt)||  ifRoot ;
		}
		var ids = ifRoot?["root"]:[];

		var summary = this.__$first(wikiXml, "content");
		if (summary==null){return ids;}
		var content = this.__$$cdata(summary);
		if (Wiki.Config.ifHTMLSection){
			item.saveSection(content, -2);
			ids.push("sections");	
			return ids;
		}
		
		if (item.save(item.getTitle(), content) && !ifRoot){ids.push("root");}
		if (!Wiki.Config.ifHTMLSection || this.__updChilds(wikiXml, this.__SECTION)) {
			ids = ids.concat(this.__$text(wikiXml, this.__IDSTAGS[this.__SECTION]).split(","));
		}
		return ids;
	},
	checkUpdate:function(wikiXml){return (Wiki.Config.ifHTMLSection && this.__$first(wikiXml, "content") !=null);},	
	// return: [["newid=oldId", ...], [idToBeRefreshed, ...]]
	update:function(wikiXml){
		var replaceIds = [];
		if (this.getAppx(this.__COMMENTS)){replaceIds = this.__updIds(wikiXml, this.__COMMENT);}

		var refreshIds=IX.Utils.loop(this.getAppxList(), [], function(acc, item){
			var appx = this.getAppx(item);
			if(appx) {
				var appxNode = this.__$first(wikiXml,  this.__MTAGS[item]);
				if (appxNode!=null) {
					appx.load(this.__cvtAppxToDesc(appxNode, item));
					acc.push(appx._id);
				}
			}
			return acc;
		}.bind(this));

		var ids = this._updatePage(wikiXml);
		if(ids.length>0){refreshIds = refreshIds.concat(ids);}

		if(this.getAppx(this.__KITEMS) && this.__updKItemList(wikiXml)){
			refreshIds.push(this._genId(this.__KITEMS,""));
		}
		if(this.getAppx(this.__SITEMS) && this.__updSItemList(wikiXml)){
			refreshIds.push(this._genId(this.__SITEMS,""));
		}
		return [replaceIds, refreshIds];
	}
},{ // handler to send to server
	__$ids:function(nodeId, tagN){return this.find(nodeId)._getAll("id").join(",").inTag(tagN);},
	__$tags:function(item){return item._hasTags()?item.getTags().join(",").inPureTag("tags"):"";},
	__$topic:function(wItem){
		var xml = wItem.loopExtTopics("", function(acc, item, idx) {
			var titem = item[0].inPureTag("title");
			if (!isEmpty(item[1])){titem += item[1].inPureTag("mapped");}
			return acc + titem.inTag("titem");
		}.bind(this));
		return wItem.getTopic().inPureTag("topic") + xml.inTag("topics", [["op","save"]]);
	},
	__$wikipage:function(wItem){
		var $model = this.__$model;
		if  (!Wiki.Config.ifHTMLSection){
			return $model(wItem)+ wItem.loopDeep("", function(acc, item){
				var attrs = [["id", item._id], ["level", item._level], ["pid", item._parent._id],["idx", item._idx], ["version", item._version]];
				return acc + $model(item).inTag("section", attrs);
			}).inTag("sections");
		}
		var list = wItem.loopAll([], function(acc, item){
			acc.push([item._level, item._title, item._content]);
			return acc;
		});
		list[0][0]=-1;
		var cvt = new Wiki.SDEPConverter();
		var node = new Wiki.Model.Unknown();
		node.save(wItem._title, cvt.generateEditing(list));
		return $model(node);
	},
	__$wiki:function(op, opXml, item){
		var docTypes =  {101:"wiki", 102:"kfolder", 103:"image",104:"rfolder",105:"ifolder", 106:"bitem", 107:"bfolder", 108:"titem"};
		return opXml.inTag("wiki", [["id",  this.getItemId()], ["version", item._version], ["op", op], ["type", docTypes[this._type]]]);
	},
	getNodeInXml:function(op){
		var item = this.find("root");
		return this.__$wiki(op, this.__$wikipage(item) + this.__$topic(item) + this.__$tags(item), item);
	},
	__$kilist:function(idList, opcode){
		var kitems = this.getAppx(this.__KITEMS);
		var getF=function(stype){return function(acc, item, idx){
			var hasV = opcode==(stype+"ki") && idList &&idList.length>idx;
			var value =  hasV?idList[idx]:(stype=="sort"?kitems._columns[item]:kitems["_" +item]);
			acc.push([item, value]);
			return acc;
		};};

		var columns = "".inTag("columns", IX.Utils.loop(["orderBy", "order"], [], getF("sort")));
		var list= {102:[], 105:["imgType"], 104:["reqType", "specType", "refType"], 106:["actionType", "cond"], 107:["actionType", "cond"]};
		var attrsList = IX.Utils.loop(["incChild"].concat(list[this._type]), [["noipp", kitems._noipp],["curp", kitems._curPIdx], ["isAll", false]], getF("load"));
		return columns.inTag("itemlist", attrsList);
	},
	__$kilistExt:function(idList){return  this.__$kilist(null, "loadki") + idList.join(",").inTag("itemlist_ids");},

	__$silist:function(idList, opcode){
		var sitems = this.getAppx(this.__SITEMS);
		var columns = "".inTag("columns", opcode=="sortsi"?[["orderBy", idList[0]], ["order", idList[1]]]: IX.Utils.loop(["orderBy", "order"], [],  function(acc, item) {
			acc.push([item, sitems._columns[item]]);
			return acc;
		})); 
		return columns.inTag("search",  [["noipp", sitems._noipp],["curp", sitems._curPIdx], ["isAll", false], ["cond", sitems._cond]]);
	},

	callServer:function(opcode, idList){
		var postXml = "";
		var op = "save";
		var $model=this.__$model;
		var $wikipage = this.__$wikipage.bind(this);
		var wItem = this.find("root");
		if (opcode =="saveItem"){
			postXml = IX.Utils.loop(idList, "", function(acc, item){
				return acc + (item==this.getPrefix(this.__TAGS)?this.__$tags(wItem):($wikipage(wItem)));
			}.bind(this));
		} else if (opcode=="saveTopic") {
			postXml = this.__$topic(wItem);
		} else if (opcode =="editTopic"){
			return window.wiki_editTopicInfo(idList);
		} else if (opcode=="saveSections") {
			postXml = $wikipage(wItem)+ idList.join(",").inTag("section_ids");
		} else if( opcode=="property"){
			return window.wiki_editProperty(wItem.getItemId());
		} else if (opcode=="toAddLinks"){   
			return window.wiki_getUrlForAddingAppendix("toAddLinks",this.getAppx(this.__LINKS)._getAll("id").join(","));
		} else if (opcode=="addQGroup"){
			return window.wiki_addQuickLinkGroup();
		} else if (opcode=="editQGroup"){
			return window.wiki_editQuickLinkGroup(idList[0]);
		}else if (opcode=="removeQItem"){
			return window.wiki_removeQuickLinkItem(idList[0], idList[1]);
		} else if (opcode=="addQuickLinksItem"){
			return window.wiki_addQuickLinksItem();
		} else if (opcode=="toLink"){
			var ids =idList[0].split("_");
			var kid = ids[ids.length>1?1:0];
			kid = kid.indexOf("/")>0?kid.substring(kid.indexOf("/")+1):kid;
			var kidType = ids.length>1?ids[0]:"";
		    return window.wiki_link2Knowledge(kid, kidType);
		} else if (opcode=="toAddAttach"){
			return window.wiki_getUrlForAddingAppendix("toAddAttach");
		} else if (opcode=="addAttach"){
			var node = this.find("unknown");
			return window.wiki_addAttachment(node._title, node._content);
		} else if (opcode.indexOf("remove")==0){// removeLinks and removeAttach
			op="delete";
			var ids = idList [0];
			var appx = this.find(ids)._appx;
			if(idList[1] in appx){
				appx[idList[1]] = null;
				//postXml = (ids=="kw")?this.__$ids(ids, "lkw_ids"):idList[1].inTag("attach_ids");
				postXml = idList[1].inTag((ids=="kw")?"lkw_ids":"attach_ids");
			}
		} else if (opcode.indexOf("Comment")>0){ //postComment and saveComment
			var cmt = this.find(idList[0]);
			var arr =[["id", cmt.getPureId()]];
			if(opcode=="postComment"){arr.push(["pid", cmt._parent.getPureId()],["idx", cmt._idx]);}
			postXml = $model(cmt).inTag("comment", arr).inTag("comments");
		} else if (opcode=="loadcmt"){
			op="load";
			var cmt = this.getAppx(this.__COMMENTS);
			postXml = "".inTag("comments", [["noipp", cmt._noipp],["curp", cmt._curPIdx], ["isAll", true]]);
		} else if (opcode=="loadki" || opcode =="sortki"){
			op="load";
			postXml  = this.__$kilist(idList, opcode);
		} else if (opcode =="actionki"){
			return wiki_folder_action(idList[0], IX.Utils.loop(idList[1],[], function(acc, item) {
				var nid = item.lastIndexOf("/");
				acc.push(nid>0?item.substring(nid+1):item);
				return acc;
			}));
		} else if (opcode =="loaditem"){
			op = "loaditem";
			postXml =  this.__$kilistExt(idList);
		} else if (opcode =="cloneki" || opcode=="moveki"){
			op=opcode.substring(0, opcode.length-2);
			var fid = idList[0]+"";
			idList.shift();
			postXml =  this.__$kilistExt(idList)+ fid.inTag("folder_ids");
		} else if (opcode =="delki"){
			op="delete";
			postXml  = this.__$kilistExt(idList);
		} else if (opcode == "grapki"){
			return window.wiki_grapItemInList(idList[0], idList[1]);
		} else if (opcode =="releasegrapki"){
			return window.wiki_releaseItemInList(idList[0], idList[1]);
		} else if (opcode =="loadsi"|| opcode =="sortsi") {
			op="load";
			postXml  = this.__$silist(idList, opcode);
		} else if (opcode =="linksi" || opcode =="linkki") {
			return window.wiki_addTopic4Items(idList);
		} else if (opcode == "newItem4Topic") {
			return window.wiki_newItem4Topic();
		} else if (opcode =="config"){
			return wiki_post_config(idList);
		} else {alert(this.i18n("callServer") + opcode);}
		wiki_post(this.__$wiki(op, postXml,  wItem));
		return true;
	}
});
