import { Client, Producer, Message, MessageId } from "pulsar-client";
import { Container, Scope, Singleton, Inject } from "typescript-ioc";
import { PulsarMasterFactory } from "../pulsar/PulsarMasterFactory";
import { PulsarSlaveFactory } from "../pulsar/PulsarSlaveFactory";
import { BaseEventHandler } from "./BaseEventHandler";
import { Payload } from "../model/Payload";
import { RedisUtil } from '../redis/RedisUtil';
import { Config } from '../config/Config'
import { log4js as logger } from '../log4js/logger'


@Singleton
export class Consumer {

    @Inject
    private pulsarMasterFactory: PulsarMasterFactory;

    @Inject
    private pulsarSlaveFactory: PulsarSlaveFactory;

    async consume(payload: Payload, baseEventHandler: BaseEventHandler) {
        logger.info('开始消费 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
        let masterClient = await this.pulsarMasterFactory.get();
        let slaveClient = await this.pulsarSlaveFactory.get();
        await Promise.all([
            this.consumeFromPulsar(masterClient, payload, baseEventHandler),
            this.consumeFromPulsar(slaveClient, payload, baseEventHandler)
        ]);
    }

    private async consumeFromPulsar(client: Client, payload: Payload, baseEventHandler: BaseEventHandler) {
        const redsiLock = Container.get(RedisUtil)
        let defaultTopic: string = `persistent://${Config.getDefaultTenant()}/${Config.getDefaultNamespace()}/${payload.getTopic()}`;
        await client.subscribe({
            topic: defaultTopic,
            subscription: Config.getSubscriptionId(),
            subscriptionType: 'Shared',
            listener: async (msg, msgConsumer) => {
                logger.info('开始listening >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
                let message: string = msg.getData().toString();
                let msgId: string = JSON.parse(message).msgId
                let msgVersion: string = msg.getProperties()["version"];
                let defaultRevisionVersion: string = Config.getDefaultVersions()[Config.getSubscriptionId()]
                if (defaultRevisionVersion) {
                    logger.info(`当前部署没有默认版本，不能消费....subscriptionId:${Config.getSubscriptionId()},DefaultVersion:${Config.getDefaultVersions()}`)
                    return
                }
                let defaultMinorVersion: string = defaultRevisionVersion.substring(0, defaultRevisionVersion.lastIndexOf("."))
                if (msgVersion != defaultMinorVersion) {
                    logger.info(`当前部署非默认版本，不能消费...msgVersion:${msgVersion},defaultMinorVersion:${defaultMinorVersion}`)
                    return
                }
                //使用Redis分布式锁锁5秒
                try {
                    const lock = await redsiLock.lock(msgId, 5000)
                    if (!lock) {
                        logger.info('获取redis分布式锁失败....')
                        msgConsumer.acknowledge(msg);
                        return
                    }
                    try {
                        await baseEventHandler.handle(msg)
                        msgConsumer.acknowledge(msg);
                    } catch (e) {
                        logger.error('执行事件处理器发生异常:' + e)
                    } finally {
                        await redsiLock.unlock(lock)
                    }
                } catch (e) {
                    logger.error('redis加锁/解锁异常,不可提交。异常信息:' + e)
                }
            },
        });
    }
}