import { IContext } from 'pip-services4-components-node';
import { ConfigParams } from 'pip-services4-components-node';
import { IReferences } from 'pip-services4-components-node';
import { IReferenceable } from 'pip-services4-components-node';
import { IOpenable } from 'pip-services4-components-node';
import { CachedCounters } from 'pip-services4-observability-node';
import { Descriptor } from 'pip-services4-components-node';
import { ContextInfo } from 'pip-services4-components-node';
import { CompositeLogger } from 'pip-services4-observability-node'
import { CompositeCounters } from 'pip-services4-observability-node'
import { Context } from 'pip-services4-components-node';

import { CounterV1 } from '../version1/CounterV1';
import { IPerfMonClientV1 } from '../version1/IPerfMonClientV1';

export abstract class AbstractPerfMon extends CachedCounters implements IReferenceable, IOpenable {
    
    protected _client: IPerfMonClientV1;
    protected _source: string;

    public constructor(client: IPerfMonClientV1) {
        super();
        this._client = client;
    }

    public configure(config: ConfigParams): void {
        super.configure(config);
        this._source = config.getAsStringWithDefault("source", this._source);
        (this._client as any).configure(config);
    }
	
    public setReferences(references: IReferences): void {
        (this._client as any).setReferences(references);
        (this._client as any)._logger = new CompositeLogger();
        (this._client as any)._counters = new CompositeCounters();
        let contextInfo = references.getOneOptional<ContextInfo>(
            new Descriptor("pip-services", "context-info", "default", "*", "1.0"));
        if (contextInfo != null && this._source == null)
            this._source = contextInfo.name;
    }

    public isOpen(): boolean {
        return (this._client as any).isOpened();
    }

    public async open(context: IContext): Promise<void> {
        await (this._client as any).open(context);
    }

    public async close(context: IContext): Promise<void> {
        await (this._client as any).close(context);
        this.dump();
    }

    public async save(counters: CounterV1[]): Promise<void> {
        counters.forEach(counter => {
            counter.source = counter.source || this._source || "unknown";
        });
        const context = Context.fromTraceId('counters');
        await this._client.writeCounters(context, counters);
    }
}
