import 'package:fis_jsonrpc/utils.dart';

enum MongoDBActionTypeEnum {
	InsertOne,
	InsertOneAsync,
	InsertMany,
	InsertManyAsync,
	DeleteOne,
	DeleteOneAsync,
	DeleteMany,
	DeleteManyAsync,
	FindOneAndDelete,
	FindOneAndDeleteAsync,
	ReplaceOne,
	ReplaceOneAsync,
	FindOneAndReplace,
	FindOneAndReplaceAsync,
	UpdateOne,
	UpdateOneAsync,
	UpdateMany,
	UpdateManyAsync,
	FindOneAndUpdate,
	FindOneAndUpdateAsync,
}

class OperationLogDTO {
	int id;
	String? collectionName;
	MongoDBActionTypeEnum actionType;
	String? bsonContent;
	String? filterContent;
	DateTime? createTime;
	String? code;
	String? sourceUrl;
	bool isSimple;

	OperationLogDTO({
		this.id = 0,
		this.collectionName,
		this.actionType = MongoDBActionTypeEnum.InsertOne,
		this.bsonContent,
		this.filterContent,
		this.createTime,
		this.code,
		this.sourceUrl,
		this.isSimple = false,
	});

	factory OperationLogDTO.fromJson(Map<String, dynamic> map) {
		return OperationLogDTO( 
			id: map['Id'],
			collectionName: map['CollectionName'],
			actionType: MongoDBActionTypeEnum.values.firstWhere((e) => e.index == map['ActionType']),
			bsonContent: map['BsonContent'],
			filterContent: map['FilterContent'],
			createTime: map['CreateTime'] != null ? DateTime.parse(map['CreateTime']) : null,
			code: map['Code'],
			sourceUrl: map['SourceUrl'],
			isSimple: map['IsSimple'],
		);
	}

	Map<String, dynamic> toJson() {
		final map = Map<String, dynamic>();
		map['Id'] = id;
		if(collectionName != null)
			map['CollectionName'] = collectionName;
		map['ActionType'] = actionType.index;
		if(bsonContent != null)
			map['BsonContent'] = bsonContent;
		if(filterContent != null)
			map['FilterContent'] = filterContent;
		if(createTime != null)
			map['CreateTime'] = JsonRpcUtils.dateFormat(createTime!);
		if(code != null)
			map['Code'] = code;
		if(sourceUrl != null)
			map['SourceUrl'] = sourceUrl;
		map['IsSimple'] = isSimple;
		return map;
	}
}

class GetOpLogsFormMasterRequest {
	int cursor;
	String? sourceUrl;

	GetOpLogsFormMasterRequest({
		this.cursor = 0,
		this.sourceUrl,
	});

	factory GetOpLogsFormMasterRequest.fromJson(Map<String, dynamic> map) {
		return GetOpLogsFormMasterRequest( 
			cursor: map['Cursor'],
			sourceUrl: map['SourceUrl'],
		);
	}

	Map<String, dynamic> toJson() {
		final map = Map<String, dynamic>();
		map['Cursor'] = cursor;
		if(sourceUrl != null)
			map['SourceUrl'] = sourceUrl;
		return map;
	}
}

class GetOpLogsByCodesFormMasterRequest {
	List<String >? codes;

	GetOpLogsByCodesFormMasterRequest({
		this.codes,
	});

	factory GetOpLogsByCodesFormMasterRequest.fromJson(Map<String, dynamic> map) {
		return GetOpLogsByCodesFormMasterRequest( 
			codes: map['Codes'] != null ? map['Codes'].cast<String>().toList() : null,
		);
	}

	Map<String, dynamic> toJson() {
		final map = Map<String, dynamic>();
		if(codes != null)
			map['Codes'] = codes;
		return map;
	}
}

class SyncOpLogToMasterRequest {
	String? collectionName;
	MongoDBActionTypeEnum actionType;
	String? bsonContent;
	String? filterContent;
	DateTime? createTime;
	String? sourceUrl;
	String? code;
	String? serverID;
	bool isSimple;

	SyncOpLogToMasterRequest({
		this.collectionName,
		this.actionType = MongoDBActionTypeEnum.InsertOne,
		this.bsonContent,
		this.filterContent,
		this.createTime,
		this.sourceUrl,
		this.code,
		this.serverID,
		this.isSimple = false,
	});

	factory SyncOpLogToMasterRequest.fromJson(Map<String, dynamic> map) {
		return SyncOpLogToMasterRequest( 
			collectionName: map['CollectionName'],
			actionType: MongoDBActionTypeEnum.values.firstWhere((e) => e.index == map['ActionType']),
			bsonContent: map['BsonContent'],
			filterContent: map['FilterContent'],
			createTime: map['CreateTime'] != null ? DateTime.parse(map['CreateTime']) : null,
			sourceUrl: map['SourceUrl'],
			code: map['Code'],
			serverID: map['ServerID'],
			isSimple: map['IsSimple'],
		);
	}

	Map<String, dynamic> toJson() {
		final map = Map<String, dynamic>();
		if(collectionName != null)
			map['CollectionName'] = collectionName;
		map['ActionType'] = actionType.index;
		if(bsonContent != null)
			map['BsonContent'] = bsonContent;
		if(filterContent != null)
			map['FilterContent'] = filterContent;
		if(createTime != null)
			map['CreateTime'] = JsonRpcUtils.dateFormat(createTime!);
		if(sourceUrl != null)
			map['SourceUrl'] = sourceUrl;
		if(code != null)
			map['Code'] = code;
		if(serverID != null)
			map['ServerID'] = serverID;
		map['IsSimple'] = isSimple;
		return map;
	}
}

enum SyncTypeEnum {
	Initiate,
	Accept,
	Reject,
	CancelInitiate,
	HeartRateJoin,
	NetworkErr,
	HeartRateLeave,
	Leave,
	Close,
	ChangeMuteState,
	ChangeVideoOpenState,
	InviteIn,
	CancelInviteIn,
	AcceptIn,
	RejectIn,
	ChangeConsultationStatus,
	Agree,
}

class SyncReceiveServiceDataRequest {
	SyncTypeEnum syncType;
	String? serviceDataJson;
	List<OperationLogDTO >? oplogs;
	String? sourceUrl;
	String? serverID;

	SyncReceiveServiceDataRequest({
		this.syncType = SyncTypeEnum.Initiate,
		this.serviceDataJson,
		this.oplogs,
		this.sourceUrl,
		this.serverID,
	});

	factory SyncReceiveServiceDataRequest.fromJson(Map<String, dynamic> map) {
		return SyncReceiveServiceDataRequest( 
			syncType: SyncTypeEnum.values.firstWhere((e) => e.index == map['SyncType']),
			serviceDataJson: map['ServiceDataJson'],
			oplogs: map['Oplogs'] != null ? (map['Oplogs'] as List).map((e)=>OperationLogDTO.fromJson(e as Map<String,dynamic>)).toList() : null,
			sourceUrl: map['SourceUrl'],
			serverID: map['ServerID'],
		);
	}

	Map<String, dynamic> toJson() {
		final map = Map<String, dynamic>();
		map['SyncType'] = syncType.index;
		if(serviceDataJson != null)
			map['ServiceDataJson'] = serviceDataJson;
		if(oplogs != null)
			map['Oplogs'] = oplogs;
		if(sourceUrl != null)
			map['SourceUrl'] = sourceUrl;
		if(serverID != null)
			map['ServerID'] = serverID;
		return map;
	}
}