import { Application, ChannelService, HandlerService, } from 'pinus';
import { ActivityModel, ActivityModelType } from '../../../db/Activity';
import { ServerlistModel } from '../../../db/Serverlist';
import { reloadResources } from '../../../pubUtils/data';
import { _getActivitiesByType, _getActivityById, _getActivities } from '../../../services/activity/activityService';

export default function (app: Application) {
    new HandlerService(app, {});
    return new ActivityRemote(app);
}

export class ActivityRemote {

    constructor(private app: Application) {
        this.app = app;
        this.channelService = app.get('channelService');
        this.loadActivities();
    }

    private channelService: ChannelService;
    private activityByServer: Map<number, number[]> = new Map();  // serverId => activityId[];
    private activities: Map<number, ActivityModelType> = new Map(); // activityId => activity
    private activityByType: Map<number, Map<number, number[]>> = new Map(); // serverId => type => activityId[];
    private groupToServer: Map<number, number[]> = new Map(); // group => serverId[];

    /**
     * 重载json资源
     */
    public async reloadResources() {
        reloadResources();
    }

    private async loadActivities() {
        let servers = await ServerlistModel.getAllServerList();
        for(let { serverId, activityGroupId } of servers) {
            for(let groupId of activityGroupId) {
                if(!this.groupToServer.has(groupId)) {
                    this.groupToServer.set(groupId, []);
                }
                this.groupToServer.get(groupId).push(serverId);
            }
        }

        let activities = await ActivityModel.findOpenAndComingActivityes();
        let activityIds: number[] = [];
        for(let activity of activities) {
            this.activities.set(activity.activityId, activity);
            activityIds.push(activity.activityId);
        }
        this.setActivityTypeAndServer();

        this.app.set('activityByServer', this.activityByServer);
        this.app.set('activityByType', this.activityByType);
        this.app.set('activities', this.activities);
    }

    private setActivityTypeAndServer() {
        this.activityByServer.clear();
        this.activityByType.clear();

        for(let [_, activity] of this.activities) {
            let servers = this.groupToServer.get(activity.activityId)||[];
            for(let serverId of servers) {
                if(!this.activityByServer.has(serverId)) {
                    this.activityByServer.set(serverId, []);
                }
                this.activityByServer.get(serverId).push(activity.activityId);

                if(!this.activityByType.has(serverId)) {
                    this.activityByType.set(serverId, new Map());
                }
                if(!this.activityByType.get(serverId).has(activity.type)) {
                    this.activityByType.get(serverId).set(activity.type, []);
                }
                this.activityByType.get(serverId).get(activity.type).push(activity.activityId);
            }
        }
    }

    public async updateActivities(activities: ActivityModelType[]) {
        let activityIds: number[] = [];
        for(let activity of activities) {
            this.activities.set(activity.activityId, activity);
            activityIds.push(activity.activityId);
        }
        this.setActivityTypeAndServer();
    }

    public async deleteActivities(activityIds: number[]) {
        for(let activityId of activityIds) {
            this.activities.delete(activityId);
        }
        this.setActivityTypeAndServer();
    }

    public async saveGroupToServer(groupId: number, serverIds: number[]) {
        this.groupToServer.set(groupId, serverIds);
        this.setActivityTypeAndServer();
    }

    public async saveActivitiesToGroup(groupId: number, activities: number[]) {
        for(let activityId of activities) {
            this.activities.get(activityId).groupId = groupId;
        }
        this.setActivityTypeAndServer();
    }

    public getActivityById(activityId: number) {
        return _getActivityById(activityId);
    }

    public getActivitiesByType(serverId: number, type: number) {
        return _getActivitiesByType(serverId, type);
    }

    public getActivities() {
        return _getActivities();
    }
}