// #ifdef H5
import './runtime'
// #endif
import TIM from './tim-wx';
import LibGenerateTestUserSig from "./lib-generate-test-usersig-es.min";

const EXPIRETIME = 604800;
const LOGTAG = '--JHIM--:';

class JhImGroup {
	constructor(jhim, groupId, groupType, name ,avatar) {
	    this.jhim = jhim;
		this.groupId = groupId;
		this.groupType = groupType;
		this.name = name;
		this.avatar = avatar;
		this.groupReady = false;
		return this;
	}
	get ready() {
		return this.jhim.ready && this.groupReady;
	}
	join(isOwner) {
		console.log(LOGTAG + 'join', this.groupId, isOwner);
		
		let join = () => {
			console.log(LOGTAG + 'dojoin', this.groupId);
			return this.jhim.tim.joinGroup({
				groupID: this.groupId,
				type: TIM.TYPES.GRP_AVCHATROOM
			}).then(res => {
				console.log(LOGTAG + 'joinGrouped', res.data.status);
				switch (res.data.status) {
					case TIM.TYPES.JOIN_STATUS_WAIT_APPROVAL: // 等待管理员同意
						break;
					case TIM.TYPES.JOIN_STATUS_SUCCESS: // 加群成功
					case TIM.TYPES.JOIN_STATUS_ALREADY_IN_GROUP: // 已经在群中
						this.groupReady = true;
						break;
				}
			});
		}

		return this.jhim.tim.searchGroupByID(this.groupId).then(() => {
			return join();
		}, () => {
			console.log(LOGTAG + 'createGroup');
			return this.jhim.tim.createGroup({
				groupID: this.groupId,
				name: this.groupId,
				type: this.groupType,
			}).then(() => {
				return join();
			});
		});
	}
	exit(dismiss) {
		console.log(LOGTAG + 'exit', this.groupId, dismiss);
		return this.jhim.tim.quitGroup(this.groupId).then(() => {
			this.groupReady = false;
		}).then(()=>{
			if(dismiss) {
				return this.jhim.tim.dismissGroup(this.groupId);;
			}else {
				return Promise.resolve();
			}
		});
	}
	getProfile() {
		return this.jhim.tim.getGroupProfile({
			groupID: this.groupId
		}).then(res => {
			return res.data.group;
		});
		// memberCount
	}
	on(cb, type) {
		if(!cb) return this;
		cb.jhimgroupcb = event => {
			let msgs = [];
			event.data.forEach(v => {
				if(v.conversationType==TIM.TYPES.CONV_GROUP && v.to==this.groupId && (!type || type==v.type)){
					msgs.push(v)
				}
			});
			if(msgs.length) cb(msgs);
		}
		this.jhim.tim.on(TIM.EVENT.MESSAGE_RECEIVED, cb.jhimgroupcb);
		return this;
	}
	off(cb) {
		if(!cb) return this;
		this.jhim.tim.off(TIM.EVENT.MESSAGE_RECEIVED, cb.jhimgroupcb);
		return this;
	}
	onReady(cb) {
		if(!cb) return this;
		if(this.jhim.ready) cb(true);//cb(this.ready);
		cb.jhimcbready = event => {
			cb(this.ready)
		}
		cb.jhimcbnotready = event => {
			cb(this.ready)
		}
		this.jhim.tim.on(TIM.EVENT.SDK_READY, cb.jhimcbready);
		this.jhim.tim.on(TIM.EVENT.SDK_NOT_READY, cb.jhimcbnotready);
		return this;
	}
	offReady(cb) {
		if(!cb) return this;
		this.tim.off(TIM.EVENT.SDK_READY, cb.jhimcbready);
		this.tim.off(TIM.EVENT.SDK_NOT_READY, cb.jhimcbnotready);
		return this;
	}
	sendText(text) {
		const message = this.jhim.tim.createTextMessage({
			to: this.groupId,
			conversationType: TIM.TYPES.CONV_GROUP,
			payload: {
				text
			},
		})
		message.nick = this.name;
		message.avatar = this.avatar;
		return this.jhim.tim.sendMessage(message).then(() => message);
	}
	sendCustomMessage(payload) {
		const message = this.tim.createCustomMessage({
			to: this.groupId,
			conversationType: TIM.TYPES.CONV_GROUP,
			payload,
		})
		message.nick = this.name;
		message.avatar = this.avatar;
		return this.tim.sendMessage(message).then(() => message);
	}
}

let instance = null;
export default class JhIm {
	static getInstance(userId, sdkAppID, secretKey, userSig) {
		if (JhIm.instance) return JhIm.instance;
		return JhIm.instance = new JhIm(userId, sdkAppID, secretKey, userSig);
	}

	constructor(userId, sdkAppID, secretKey, userSig) {
		this.userId = userId;
		this.sdkAppID = sdkAppID;
		this.secretKey = secretKey;
		this.tim = TIM.create({
			SDKAppID: this.sdkAppID
		});
		const generator = new LibGenerateTestUserSig(this.sdkAppID, this.secretKey, EXPIRETIME);
		this.userSig = userSig || generator.genTestUserSig(this.userId);
		this.ready = false;
		this.roomId = null;
		this.groupReady = false;

		// 0 普通级别,日志量较多,接入时建议使用
		// 1 release级别,SDK 输出关键信息,生产环境时建议使用
		// 2 告警级别,SDK 只输出告警和错误级别的日志
		// 3 错误级别,SDK 只输出错误级别的日志
		// 4 无日志级别,SDK 将不打印任何日志
		this.tim.setLogLevel(3);
		
		this.TYPES = TIM.TYPES;
		this.EVENT = TIM.EVENT;

		this.tim.on(TIM.EVENT.MESSAGE_RECEIVED, event => {
			console.log(LOGTAG + 'recv', event);
			let msgs = [];
			event.data.forEach(v => {
				// https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/Message.html
				if (v.type == TIM.TYPES.MSG_TEXT) {
					msgs.push(v);
					msgs.push({
						type: v.type,
						name: v.nick,
						avatar: v.avatar,
						text: v.payload.text,
						conversationType: v.conversationType,
						time: v.time,
					})
				} else if (v.type == "TIMGroupTipElem") {
					this.onIMGroupTipElem && this.onIMGroupTipElem(v.payload);
				}
			})

			this.onIMMessageReceived && this.onIMMessageReceived(msgs);
		}, this);

		this.tim.on(TIM.EVENT.SDK_READY, event => {
			this.ready = true;
		}, this);
		this.tim.on(TIM.EVENT.SDK_NOT_READY, event => {
			this.ready = false;
		}, this);

		return this;
	}
	destory() {
		this.tim = null;
	}
	on(name, cb) {
		// 事件
		// https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/module-EVENT.html
		// 1. 收到消息 TIM.EVENT.MESSAGE_RECEIVED
		// https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/Message.html
		// -- type,
		// -- nick,
		// -- avatar,
		// -- payload
		// -- conversationType
		// -- time,
		// 2. 接入 TIM.EVENT.SDK_READY
		// 3. 掉线 TIM.EVENT.SDK_NOT_READY
		// 4. 收到被踢下线通知 TIM.EVENT.KICKED_OUT
		// TIM.EVENT.KICKED_OUT
		// 5. 收到 SDK 发生错误通知 TIM.EVENT.ERROR
		// - event.name - TIM.EVENT.ERROR
		// - event.data.code - 错误码
		// - event.data.message - 错误信息
		this.tim.on(name, cb);
		return this;
	}
	off(name, cb) {
		this.tim.off(name, cb);
		return this;
	}
	login(name, avatar) {
		if (this.ready) return Promise.resolve();
	
		console.log(LOGTAG + 'login');
		this.name = name;
		this.avatar = avatar;
		
		return new Promise(resolve => {
			let cb = event => {
				console.log(LOGTAG + 'ready');
				this.ready = true;
				this.tim.updateMyProfile({
					nick: name,
					avatar: avatar,
					allowType: TIM.TYPES.ALLOW_TYPE_ALLOW_ANY
				});
				// this.tim.on(TIM.EVENT.MESSAGE_RECEIVED, event=>{
				// 	debugger
				// });
				resolve();
				this.tim.off(TIM.EVENT.SDK_READY, cb, this);
			}
			this.tim.on(TIM.EVENT.SDK_READY, cb, this);
			this.tim.login({
				userID: this.userId,
				userSig: this.userSig,
			})
		});
	}
	logout() {
		return this.tim.logout().then(() => {
			this.ready = false;
		});
	}
	onReady(cb) {
		if(!cb) return this;
		cb.jhimcbready = event => {
			this.ready = true;
		}
		cb.jhimcbnotready = event => {
			this.ready = false;
		}
		this.tim.on(TIM.EVENT.SDK_READY, cb.jhimcbready);
		this.tim.on(TIM.EVENT.SDK_NOT_READY, cb.jhimcbnotready);
	}
	offReady(cb) {
		if(!cb) return this;
		this.tim.off(TIM.EVENT.SDK_READY, cb.jhimcbready);
		this.tim.off(TIM.EVENT.SDK_NOT_READY, cb.jhimcbnotready);
	}
	createGroup(groupId, type=TIM.TYPES.GRP_AVCHATROOM) {
		return new JhImGroup(this, groupId, type, this.name ,this.avatar);
	}
	onMessageRecv(cb, from, type, conversationType=TIM.TIM.TYPES.CONV_C2C) {
		if(!cb) return;
		cb.jhimcb = event => {
			let msgs = event.data.filter( v=> {
				if(from && v.from != from) return false;
				if(conversationType && v.conversationType != conversationType) return false;
				if(type && v.type != type) return false;
				return true;
			});
			msgs.length && cb(msgs);
		}
		this.tim.on(TIM.EVENT.MESSAGE_RECEIVED, cb.jhimcb);
	}
	offMessageRecv(cb) {
		if(!cb) return;
		this.time.off(TIM.EVENT.MESSAGE_RECEIVED,cb.jhimcb);
	}
	sendText(text, to) {
		const message = this.tim.createTextMessage({
			to,
			conversationType: TIM.TIM.TYPES.CONV_C2C,
			payload: {
				text
			},
		})
		message.nick = this.name;
		message.avatar = this.avatar;
		return this.tim.sendMessage(message).then(() => message);
	}
	sendCustomMessage(payload, to) {
		const message = this.tim.createCustomMessage({
			to: to,
			conversationType: TIM.TYPES.CONV_C2C,
			payload,
		})
		message.nick = this.name;
		message.avatar = this.avatar;
		return this.tim.sendMessage(message).then(() => message);
	}
}