import DnsAnswer, { IDnsAnswer } from './DnsAnswer';
import DnsQuestion, { IDnsQuestion } from './DnsQuestion';
import ResultRule, { IResultRule } from './ResultRule';

// This file was autogenerated. Please do not change.
// All changes will be overwrited on commit.
export interface IQueryLogItem {
    answer?: IDnsAnswer[];
    answer_dnssec?: boolean;
    client?: string;
    client_id?: string;
    client_proto?: any;
    elapsedMs?: string;
    filterId?: number;
    original_answer?: IDnsAnswer[];
    question?: IDnsQuestion;
    reason?: string;
    rule?: string;
    rules?: IResultRule[];
    service_name?: string;
    status?: string;
    time?: string;
    upstream?: string;
}

export default class QueryLogItem {
    readonly _answer: DnsAnswer[] | undefined;

    get answer(): DnsAnswer[] | undefined {
        return this._answer;
    }

    readonly _answer_dnssec: boolean | undefined;

    get answerDnssec(): boolean | undefined {
        return this._answer_dnssec;
    }

    readonly _client: string | undefined;

    /**
     * Description: The client's IP address.
     *
     * Example: 192.168.0.1
     */
    get client(): string | undefined {
        return this._client;
    }

    readonly _client_id: string | undefined;

    /**
     * Description: The client ID, if provided in DOH, DOQ, or DOT.
     *
     * Example: cli123
     */
    get clientId(): string | undefined {
        return this._client_id;
    }

    readonly _client_proto: any | undefined;

    get clientProto(): any | undefined {
        return this._client_proto;
    }

    readonly _elapsedMs: string | undefined;

    /**
     * Description: undefined
     * Example: 54.023928
     */
    get elapsedMs(): string | undefined {
        return this._elapsedMs;
    }

    readonly _filterId: number | undefined;

    /**
     * Description: In case if there's a rule applied to this DNS request, this is ID of the filter list that the rule belongs to.
     * Deprecated: use `rules[*].filter_list_id` instead.
     *
     * Example: 123123
     */
    get filterId(): number | undefined {
        return this._filterId;
    }

    readonly _original_answer: DnsAnswer[] | undefined;

    /** */
    get originalAnswer(): DnsAnswer[] | undefined {
        return this._original_answer;
    }

    readonly _question: DnsQuestion | undefined;

    get question(): DnsQuestion | undefined {
        return this._question;
    }

    readonly _reason: string | undefined;

    /** */
    get reason(): string | undefined {
        return this._reason;
    }

    readonly _rule: string | undefined;

    /**
     * Description: Filtering rule applied to the request (if any).
     * Deprecated: use `rules[*].text` instead.
     *
     * Example: ||example.org^
     */
    get rule(): string | undefined {
        return this._rule;
    }

    readonly _rules: ResultRule[] | undefined;

    /** */
    get rules(): ResultRule[] | undefined {
        return this._rules;
    }

    readonly _service_name: string | undefined;

    /** */
    get serviceName(): string | undefined {
        return this._service_name;
    }

    readonly _status: string | undefined;

    /**
     * Description: DNS response status
     * Example: NOERROR
     */
    get status(): string | undefined {
        return this._status;
    }

    readonly _time: string | undefined;

    /**
     * Description: DNS request processing start time
     * Example: 2018-11-26T00:02:41+03:00
     */
    get time(): string | undefined {
        return this._time;
    }

    readonly _upstream: string | undefined;

    /** */
    get upstream(): string | undefined {
        return this._upstream;
    }

    constructor(props: IQueryLogItem) {
        if (props.answer) {
            this._answer = props.answer.map((p) => new DnsAnswer(p));
        }
        if (typeof props.answer_dnssec === 'boolean') {
            this._answer_dnssec = props.answer_dnssec;
        }
        if (typeof props.client === 'string') {
            this._client = props.client.trim();
        }
        if (typeof props.client_id === 'string') {
            this._client_id = props.client_id.trim();
        }
        if (props.client_proto) {
            this._client_proto = props.client_proto;
        }
        if (typeof props.elapsedMs === 'string') {
            this._elapsedMs = props.elapsedMs.trim();
        }
        if (typeof props.filterId === 'number') {
            this._filterId = props.filterId;
        }
        if (props.original_answer) {
            this._original_answer = props.original_answer.map((p) => new DnsAnswer(p));
        }
        if (props.question) {
            this._question = new DnsQuestion(props.question);
        }
        if (typeof props.reason === 'string') {
            this._reason = props.reason.trim();
        }
        if (typeof props.rule === 'string') {
            this._rule = props.rule.trim();
        }
        if (props.rules) {
            this._rules = props.rules.map((p) => new ResultRule(p));
        }
        if (typeof props.service_name === 'string') {
            this._service_name = props.service_name.trim();
        }
        if (typeof props.status === 'string') {
            this._status = props.status.trim();
        }
        if (typeof props.time === 'string') {
            this._time = props.time.trim();
        }
        if (typeof props.upstream === 'string') {
            this._upstream = props.upstream.trim();
        }
    }

    serialize(): IQueryLogItem {
        const data: IQueryLogItem = {
        };
        if (typeof this._answer !== 'undefined') {
            data.answer = this._answer.map((p) => p.serialize());
        }
        if (typeof this._answer_dnssec !== 'undefined') {
            data.answer_dnssec = this._answer_dnssec;
        }
        if (typeof this._client !== 'undefined') {
            data.client = this._client;
        }
        if (typeof this._client_id !== 'undefined') {
            data.client_id = this._client_id;
        }
        if (typeof this._client_proto !== 'undefined') {
            data.client_proto = this._client_proto;
        }
        if (typeof this._elapsedMs !== 'undefined') {
            data.elapsedMs = this._elapsedMs;
        }
        if (typeof this._filterId !== 'undefined') {
            data.filterId = this._filterId;
        }
        if (typeof this._original_answer !== 'undefined') {
            data.original_answer = this._original_answer.map((p) => p.serialize());
        }
        if (typeof this._question !== 'undefined') {
            data.question = this._question.serialize();
        }
        if (typeof this._reason !== 'undefined') {
            data.reason = this._reason;
        }
        if (typeof this._rule !== 'undefined') {
            data.rule = this._rule;
        }
        if (typeof this._rules !== 'undefined') {
            data.rules = this._rules.map((p) => p.serialize());
        }
        if (typeof this._service_name !== 'undefined') {
            data.service_name = this._service_name;
        }
        if (typeof this._status !== 'undefined') {
            data.status = this._status;
        }
        if (typeof this._time !== 'undefined') {
            data.time = this._time;
        }
        if (typeof this._upstream !== 'undefined') {
            data.upstream = this._upstream;
        }
        return data;
    }

    validate(): string[] {
        const validate = {
            answer: !this._answer ? true : this._answer.reduce((result, p) => result && p.validate().length === 0, true),
            original_answer: !this._original_answer ? true : this._original_answer.reduce((result, p) => result && p.validate().length === 0, true),
            upstream: !this._upstream ? true : typeof this._upstream === 'string' && !this._upstream ? true : this._upstream,
            answer_dnssec: !this._answer_dnssec ? true : typeof this._answer_dnssec === 'boolean',
            client: !this._client ? true : typeof this._client === 'string' && !this._client ? true : this._client,
            client_id: !this._client_id ? true : typeof this._client_id === 'string' && !this._client_id ? true : this._client_id,
            elapsedMs: !this._elapsedMs ? true : typeof this._elapsedMs === 'string' && !this._elapsedMs ? true : this._elapsedMs,
            question: !this._question ? true : this._question.validate().length === 0,
            filterId: !this._filterId ? true : typeof this._filterId === 'number',
            rule: !this._rule ? true : typeof this._rule === 'string' && !this._rule ? true : this._rule,
            rules: !this._rules ? true : this._rules.reduce((result, p) => result && p.validate().length === 0, true),
            reason: !this._reason ? true : typeof this._reason === 'string' && !this._reason ? true : this._reason,
            service_name: !this._service_name ? true : typeof this._service_name === 'string' && !this._service_name ? true : this._service_name,
            status: !this._status ? true : typeof this._status === 'string' && !this._status ? true : this._status,
            time: !this._time ? true : typeof this._time === 'string' && !this._time ? true : this._time,
        };
        const isError: string[] = [];
        Object.keys(validate).forEach((key) => {
            if (!(validate as any)[key]) {
                isError.push(key);
            }
        });
        return isError;
    }

    update(props: Partial<IQueryLogItem>): QueryLogItem {
        return new QueryLogItem({ ...this.serialize(), ...props });
    }
}
