/*
 * 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 Shepherd from 'shepherd.js';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { TourProviderService } from './tour-provider.service';
import Step from 'shepherd.js/src/types/step';
import StepOptions = Step.StepOptions;

@Injectable({ providedIn: 'root' })
export class ShepherdService {
    currentTour: Shepherd.Tour;
    currentTourSettings: any;
    timeWaitMillis: number;

    constructor(
        private router: Router,
        private tourProviderService: TourProviderService,
    ) {
        this.timeWaitMillis = tourProviderService.getTime();
    }

    makeTour(currentTourSettings) {
        const tour = new Shepherd.Tour({
            confirmCancel: true,
            confirmCancelMessage: 'Do you really want to cancel the tour?',
            defaultStepOptions: {
                classes: 'shadow-md bg-purple-dark',
                scrollTo: true,
                // showCancelLink: true
            },
        });

        currentTourSettings.steps.forEach(step => {
            tour.addStep(this.makeStep(tour, step));
        });

        return tour;
    }

    makeStep(tour, step) {
        const stepDefinition: StepOptions = {
            title: step.title,
            text: step.text,
            classes: step.classes,
            id: step.stepId,
            buttons: this.generateButtons(tour, step.buttons),
        };

        if (step.attachToElement) {
            Object.assign(stepDefinition, {
                attachTo: {
                    element: step.attachToElement,
                    on: step.attachPosition,
                },
            });
        }

        return stepDefinition;
    }

    generateButtons(tour, buttons) {
        const generatedButtons = [];
        buttons.forEach(button => {
            generatedButtons.push(this.generateButton(tour, button));
        });
        return generatedButtons;
    }

    generateButton(tour, button) {
        if (button === 'back') {
            return this.makeBackButton(tour);
        } else if (button === 'next') {
            return this.makeNextButton(tour);
        } else if (button === 'cancel') {
            return this.makeCancelButton(tour);
        } else if (button === 'dashboard') {
            return this.makeStartDashboardTutorialButton();
        } else if (button === 'pipeline-tutorial') {
            return this.makeStartPipelineTutorialButton();
        }
    }

    startTour(tourSettings) {
        this.currentTourSettings = tourSettings;
        this.currentTour = this.makeTour(this.currentTourSettings);
        this.currentTour.start();
    }

    makeCancelButton(tour) {
        return {
            action: tour.cancel,
            classes: 'shepherd-button-secondary',
            text: 'Exit Tour',
        };
    }

    makeNextButton(tour) {
        return {
            action: tour.next,
            text: 'Next',
        };
    }

    makeBackButton(tour) {
        return {
            action: tour.back,
            classes: 'shepherd-button-secondary',
            text: 'Back',
        };
    }

    makeStartDashboardTutorialButton() {
        return {
            action: this.switchAndStartDashboardTour(),
            text: 'Dashboard Tutorial',
        };
    }

    makeStartPipelineTutorialButton() {
        return {
            action: () => {
                this.currentTour.complete();
                this.router.navigate(['pipelines'], {
                    queryParams: { startTutorial: true },
                });
            },
            text: 'Start pipeline tutorial',
        };
    }

    trigger(actionId) {
        if (Shepherd.activeTour) {
            if (
                this.shouldTrigger(
                    actionId,
                    this.currentTour.getCurrentStep().id,
                )
            ) {
                setTimeout(
                    () => this.currentTour.next(),
                    this.tourProviderService.getTime(),
                );
            }
        }
    }

    shouldTrigger(actionId, currentStep) {
        return this.currentTourSettings.matchingSteps.some(el => {
            return el.actionId === actionId && el.currentStep === currentStep;
        });
    }

    isTourActive() {
        return Shepherd.activeTour;
    }

    hideCurrentStep() {
        Shepherd.activeTour.getCurrentStep().hide();
    }

    switchAndStartDashboardTour() {
        this.router.navigateByUrl('dashboard');
    }

    startPipelineTour() {
        this.startTour(this.tourProviderService.getTourById('create-pipeline'));
    }

    startDashboardTour() {
        this.startTour(this.tourProviderService.getTourById('dashboard'));
    }

    startAdapterTour() {
        this.startTour(this.tourProviderService.getTourById('adapter'));
    }

    setTimeWaitMillis(value) {
        this.tourProviderService.setTime(value);
    }

    getTimeWaitMillis() {
        return this.tourProviderService.getTime();
    }
}
