/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

import { TransformationRuleService } from './transformation-rule.service';
import {
    CreateNestedRuleDescription,
    EventPropertyNested,
    EventPropertyPrimitive,
    EventPropertyUnion,
    EventSchema,
    MoveRuleDescription,
    RenameRuleDescription,
} from '@streampipes/platform-services';

describe('TransformationRuleService', () => {
    const service = new TransformationRuleService();

    it('Get complete key from schema nested', () => {
        const eventProperties: EventPropertyUnion[] = [];
        const eventPropertyPrimitive: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        eventPropertyPrimitive.elementId = 'id_1';
        eventPropertyPrimitive.runtimeName = 'a';
        const eventPropertyNested: EventPropertyNested =
            new EventPropertyNested();
        eventPropertyNested.elementId = 'id_2';
        eventPropertyNested.runtimeName = 'b';
        eventPropertyNested.eventProperties = [];
        eventPropertyNested.eventProperties.push(eventPropertyPrimitive);
        eventProperties.push(eventPropertyNested);

        const result: string = service.getCompleteRuntimeNameKey(
            eventProperties,
            'id_1',
        );

        expect(result).toBe('b.a');
    });

    it('Get complete key from schema primitve', () => {
        const eventProperties: EventPropertyUnion[] = [];
        const eventPropertyPrimitive: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        eventPropertyPrimitive.elementId = 'id_1';
        eventPropertyPrimitive.runtimeName = 'a';

        eventProperties.push(eventPropertyPrimitive);

        const result: string = service.getCompleteRuntimeNameKey(
            eventProperties,
            'id_1',
        );

        expect(result).toBe('a');
    });

    it('check get all ids with one id', () => {
        const eventProperties: EventPropertyUnion[] = [];
        const eventPropertyPrimitive: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        eventPropertyPrimitive.elementId = 'id_1';
        eventProperties.push(eventPropertyPrimitive);

        const result: string[] = service.getAllIds(eventProperties);
        expect(result.length).toBe(1);
        expect(result[0]).toBe('id_1');
    });

    it('check get all ids with multiple ids', () => {
        const eventProperties: EventPropertyUnion[] = [];
        const eventPropertyPrimitive: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        eventPropertyPrimitive.elementId = 'id_1';
        const eventPropertyPrimitive1: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        eventPropertyPrimitive1.elementId = 'id_2';
        const eventPropertyNested: EventPropertyNested =
            new EventPropertyNested();
        eventPropertyNested.elementId = 'id_3';
        eventPropertyNested.eventProperties = [];
        eventPropertyNested.eventProperties.push(eventPropertyPrimitive1);

        eventProperties.push(eventPropertyPrimitive);
        eventProperties.push(eventPropertyNested);

        const result: string[] = service.getAllIds(eventProperties);
        expect(result.length).toBe(3);
        expect(result[0]).toBe('id_1');
        expect(result[2]).toBe('id_2');
        expect(result[1]).toBe('id_3');
    });

    it('Create Nested Rules simple', () => {
        const oldEventSchema: EventSchema = new EventSchema();
        oldEventSchema.eventProperties = [];

        const newEventSchema: EventSchema = new EventSchema();
        const propertyNested: EventPropertyNested = new EventPropertyNested();
        propertyNested.eventProperties = [];
        propertyNested.elementId = 'id';
        propertyNested.runtimeName = 'a';
        newEventSchema.eventProperties = [];
        newEventSchema.eventProperties.push(propertyNested);

        const result: CreateNestedRuleDescription[] =
            service.getCreateNestedRules(
                newEventSchema.eventProperties,
                oldEventSchema,
                newEventSchema,
            );

        expect(result.length).toBe(1);
        expect(result[0].runtimeKey).toBe('a');
    });

    it('Create Nested Rules nested', () => {
        const oldEventSchema: EventSchema = new EventSchema();
        oldEventSchema.eventProperties = [];

        const newEventSchema: EventSchema = new EventSchema();
        newEventSchema.eventProperties = [];
        const nestedNested: EventPropertyNested = new EventPropertyNested();
        nestedNested.runtimeName = 'a';
        nestedNested.elementId = 'deepnested';
        nestedNested.eventProperties = [];

        const nestedProperty: EventPropertyNested = new EventPropertyNested();
        nestedProperty.runtimeName = 'b';
        nestedNested.elementId = 'nested';
        nestedProperty.eventProperties = [];
        nestedNested.eventProperties.push(nestedProperty);
        newEventSchema.eventProperties.push(nestedNested);

        const result: CreateNestedRuleDescription[] =
            service.getCreateNestedRules(
                newEventSchema.eventProperties,
                oldEventSchema,
                newEventSchema,
            );

        expect(result.length).toBe(2);
        expect(result[0].runtimeKey).toBe('a');
        expect(result[1].runtimeKey).toBe('a.b');
    });

    it('Create Move Rules simple', () => {
        const oldEventSchema: EventSchema = new EventSchema();
        const oldPropertyToMove: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        oldPropertyToMove.runtimeName = 'a';
        oldPropertyToMove.elementId = 'a1';
        const oldNestedProperty: EventPropertyNested =
            new EventPropertyNested();
        oldNestedProperty.runtimeName = 'b';
        oldNestedProperty.elementId = 'b1';
        oldNestedProperty.eventProperties = [];
        oldEventSchema.eventProperties = [];
        oldEventSchema.eventProperties.push(oldPropertyToMove);
        oldEventSchema.eventProperties.push(oldNestedProperty);

        const newEventSchema: EventSchema = new EventSchema();
        newEventSchema.eventProperties = [];
        const newPropertyToMove: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        newPropertyToMove.runtimeName = 'a';
        newPropertyToMove.elementId = 'a1';
        const newNestedProperty: EventPropertyNested =
            new EventPropertyNested();
        newNestedProperty.runtimeName = 'b';
        newNestedProperty.elementId = 'b1';
        newNestedProperty.eventProperties = [];
        newNestedProperty.eventProperties.push(newPropertyToMove);
        newEventSchema.eventProperties.push(newNestedProperty);

        const result: MoveRuleDescription[] = service.getMoveRules(
            newEventSchema.eventProperties,
            oldEventSchema,
            newEventSchema,
        );

        expect(result.length).toBe(1);
        expect(result[0].oldRuntimeKey).toBe('a');
    });

    it('Rename simple', () => {
        const oldEventSchema: EventSchema = new EventSchema();
        const oldEventPropertyPrimitive: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        oldEventPropertyPrimitive.elementId = 'id_1';
        oldEventPropertyPrimitive.runtimeName = 'a';
        oldEventSchema.eventProperties = [];
        oldEventSchema.eventProperties.push(oldEventPropertyPrimitive);

        const newEventSchema: EventSchema = new EventSchema();
        const newEventPropertyPrimitive: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        newEventPropertyPrimitive.elementId = 'id_1';
        newEventPropertyPrimitive.runtimeName = 'b';
        newEventSchema.eventProperties = [];
        newEventSchema.eventProperties.push(newEventPropertyPrimitive);

        const result: RenameRuleDescription[] = service.getRenameRules(
            newEventSchema.eventProperties,
            oldEventSchema,
            newEventSchema,
        );

        expect(result.length).toBe(1);
        expect(result[0].oldRuntimeKey).toBe('a');
        expect(result[0].newRuntimeKey).toBe('b');
    });

    it('Rename nested', () => {
        const oldEventSchema: EventSchema = new EventSchema();
        const oldNestedEventProperty: EventPropertyNested =
            new EventPropertyNested();
        oldNestedEventProperty.elementId = 'id_2';
        oldNestedEventProperty.runtimeName = 'b';
        oldNestedEventProperty.eventProperties = [];
        const oldEventPropertyPrimitive: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        oldEventPropertyPrimitive.elementId = 'id_1';
        oldEventPropertyPrimitive.runtimeName = 'a';
        oldNestedEventProperty.eventProperties.push(oldEventPropertyPrimitive);
        oldEventSchema.eventProperties = [];
        oldEventSchema.eventProperties.push(oldNestedEventProperty);

        const newEventSchema: EventSchema = new EventSchema();
        const newNestedEventProperty: EventPropertyNested =
            new EventPropertyNested();
        newNestedEventProperty.elementId = 'id_2';
        newNestedEventProperty.runtimeName = 'b';
        const newEventPropertyPrimitive: EventPropertyPrimitive =
            new EventPropertyPrimitive();
        newEventPropertyPrimitive.elementId = 'id_1';
        newEventPropertyPrimitive.runtimeName = 'b';
        newNestedEventProperty.eventProperties = [];
        newNestedEventProperty.eventProperties.push(newEventPropertyPrimitive);
        newEventSchema.eventProperties = [];
        newEventSchema.eventProperties.push(newNestedEventProperty);

        const result: RenameRuleDescription[] = service.getRenameRules(
            newEventSchema.eventProperties,
            oldEventSchema,
            newEventSchema,
        );

        expect(result.length).toBe(1);
        expect(result[0].oldRuntimeKey).toBe('b.a');
        expect(result[0].newRuntimeKey).toBe('b.b');
    });
});
