/*
    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.
 */
package org.apache.wiki.workflow;

import java.math.BigDecimal;
import java.security.Principal;
import java.util.Date;

import org.apache.wiki.api.exceptions.WikiException;
import org.apache.wiki.auth.GroupPrincipal;
import org.apache.wiki.auth.WikiPrincipal;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class WorkflowTest
{
    Workflow w;

    Task initTask;

    Decision decision;

    Task finishTask;

    String ATTR = "TestAttribute";

    @BeforeEach
    public void setUp() throws Exception
    {
        // Create workflow; owner is test user
        w = new Workflow("workflow.myworkflow", new WikiPrincipal("Owner1"));

        // Create custom initialization task
        initTask = new TaskTest.NormalTask(w);

        // Create finish task
        finishTask = new TaskTest.NormalTask(w);

        // Create an intermetidate decision step
        Principal actor = new GroupPrincipal("Admin");
        decision = new SimpleDecision(w, "decision.AdminDecision", actor);

        // Hook the steps together
        initTask.addSuccessor(Outcome.STEP_COMPLETE, decision);
        decision.addSuccessor(Outcome.DECISION_APPROVE, finishTask);

        // Stash page name as message attribute
        w.addMessageArgument("MyPage");

        // Set workflow's first step
        w.setFirstStep(initTask);
    }

    @Test
    public void testWorkflow()
    {
        // Make sure everything is set to their proper default values
        Assertions.assertNull(w.getCurrentStep());
        Assertions.assertNull(w.getCurrentActor());
        Assertions.assertEquals(0, w.getHistory().size());
        Assertions.assertEquals(Workflow.ID_NOT_SET, w.getId());
        Assertions.assertNull(w.getWorkflowManager());
        Assertions.assertEquals(new WikiPrincipal("Owner1"), w.getOwner());
        Assertions.assertEquals(Workflow.CREATED, w.getCurrentState());
        Assertions.assertEquals(Workflow.TIME_NOT_SET, w.getStartTime());
        Assertions.assertEquals(Workflow.TIME_NOT_SET, w.getEndTime());
    }

    @Test
    public void testSetWorkflowManager()
    {
        Assertions.assertNull(w.getWorkflowManager());
        WorkflowManager m = new WorkflowManager();
        w.setWorkflowManager(m);
        Assertions.assertEquals(m, w.getWorkflowManager());
    }

    @Test
    public void testGetSetAttribute()
    {
        Assertions.assertNull(w.getAttribute(ATTR));
        w.setAttribute(ATTR, "Test String");
        Assertions.assertNotNull(w.getAttribute(ATTR));
        Assertions.assertEquals("Test String", w.getAttribute(ATTR));
    }

    @Test
    public void testGetMessageArgs() throws WikiException
    {
        Object[] args;

        // Before start, arg1=Owner1, arg2=- (no current actor), arg3=MyPage
        args = w.getMessageArguments();
        Assertions.assertEquals("Owner1", args[0]);
        Assertions.assertEquals("-",      args[1]);
        Assertions.assertEquals("MyPage", args[2]);

        // After start (at Decision), arg1=Owner1, arg2=Admin, arg3=MyPage
        w.start();
        args = w.getMessageArguments();
        Assertions.assertEquals("Owner1", args[0]);
        Assertions.assertEquals("Admin", args[1]);
        Assertions.assertEquals("MyPage", args[2]);

        // After end, arg1=Owner1, arg2=-, arg3=MyPage
        decision.decide(Outcome.DECISION_APPROVE);
        args = w.getMessageArguments();
        Assertions.assertEquals("Owner1", args[0]);
        Assertions.assertEquals("-", args[1]);
        Assertions.assertEquals("MyPage", args[2]);
    }

    @Test
    public void testGetMessageArgObjects()
    {
        // Try passing some valid object types: Date, Number
        w.addMessageArgument(new Date());
        w.addMessageArgument(new Integer(1));
        w.addMessageArgument(new Double(2));
        w.addMessageArgument(new BigDecimal(3.14));

        // Try passing an invalid one: e.g., a Workflow (it should Assertions.fail)
        try
        {
            w.addMessageArgument(w);
        }
        catch (IllegalArgumentException e)
        {
            // Swallow
            return;
        }
        // We should never get here
        Assertions.fail("Illegal argument passed...");
    }

    @Test
    public void testGetMessageKey()
    {
        Assertions.assertEquals("workflow.myworkflow", w.getMessageKey());
    }

    @Test
    public void testGetOwner()
    {
        Assertions.assertEquals(new WikiPrincipal("Owner1"), w.getOwner());
    }

    @Test
    public void testStart() throws WikiException
    {
        Assertions.assertFalse(w.isStarted());
        w.start();
        Assertions.assertTrue(w.isStarted());
    }

    @Test
    public void testWaitstate() throws WikiException
    {
        w.start();

        // Default workflow should have hit the Decision step and put itself
        // into WAITING
        Assertions.assertEquals(Workflow.WAITING, w.getCurrentState());
    }

    @Test
    public void testRestart() throws WikiException
    {
        w.start();

        // Default workflow should have hit the Decision step and put itself
        // into WAITING
        Assertions.assertEquals(Workflow.WAITING, w.getCurrentState());
        w.restart();
        Assertions.assertEquals(Workflow.WAITING, w.getCurrentState());
    }

    @Test
    public void testAbortBeforeStart() throws WikiException
    {
        // Workflow hasn't been started yet
        Assertions.assertFalse(w.isAborted());
        w.abort();
        Assertions.assertTrue(w.isAborted());

        // Try to start anyway
        try
        {
            w.start();
        }
        catch (IllegalStateException e)
        {
            // Swallow
            return;
        }
        // We should never get here
        Assertions.fail("Workflow allowed itself to be started even though it was aborted!");
    }

    @Test
    public void testAbortDuringWait() throws WikiException
    {
        // Start workflow, then abort while in WAITING state
        Assertions.assertFalse(w.isAborted());
        w.start();
        w.abort();
        Assertions.assertTrue(w.isAborted());

        // Try to restart anyway
        try
        {
            w.restart();
        }
        catch (IllegalStateException e)
        {
            // Swallow
            return;
        }
        // We should never get here
        Assertions.fail("Workflow allowed itself to be re-started even though it was aborted!");
    }

    @Test
    public void testAbortAfterCompletion() throws WikiException
    {
        // Start workflow, then abort after completion
        Assertions.assertFalse(w.isAborted());
        w.start();
        Decision d = (Decision) w.getCurrentStep();
        d.decide(Outcome.DECISION_APPROVE);

        // Try to abort anyway
        try
        {
            w.abort();
            Assertions.assertTrue(w.isAborted());
        }
        catch (IllegalStateException e)
        {
            // Swallow
            return;
        }
        // We should never get here
        Assertions.fail("Workflow allowed itself to be aborted even though it was completed!");
    }

    @Test
    public void testCurrentState() throws WikiException
    {
        Assertions.assertEquals(Workflow.CREATED, w.getCurrentState());
        w.start();
        Assertions.assertEquals(Workflow.WAITING, w.getCurrentState());
        Decision d = (Decision) w.getCurrentStep();
        d.decide(Outcome.DECISION_APPROVE);
        Assertions.assertEquals(Workflow.COMPLETED, w.getCurrentState());
    }

    @Test
    public void testCurrentStep() throws WikiException
    {
        Assertions.assertNull(w.getCurrentStep());
        w.start();

        // Workflow stops at the decision step
        Assertions.assertEquals(decision, w.getCurrentStep());
        Decision d = (Decision) w.getCurrentStep();
        d.decide(Outcome.DECISION_APPROVE);

        // After we decide, it blows through step 3 and leaves us with a null
        // step (done)
        Assertions.assertNull(w.getCurrentStep());
    }

    @Test
    public void testPreviousStep() throws WikiException
    {
        // If not started, no previous steps available for anything
        Assertions.assertNull(w.getPreviousStep());
        Assertions.assertEquals(null, w.previousStep(initTask));
        Assertions.assertEquals(null, w.previousStep(decision));
        Assertions.assertEquals(null, w.previousStep(finishTask));

        // Once we start, initTask and decisions' predecessors are known, but
        // finish task is indeterminate
        w.start();
        Assertions.assertEquals(null, w.previousStep(initTask));
        Assertions.assertEquals(initTask, w.previousStep(decision));
        Assertions.assertEquals(null, w.previousStep(finishTask));

        // Once we decide, the finish task returns the correct predecessor
        Decision d = (Decision) w.getCurrentStep();
        d.decide(Outcome.DECISION_APPROVE);
        Assertions.assertEquals(null, w.previousStep(initTask));
        Assertions.assertEquals(initTask, w.previousStep(decision));
        Assertions.assertEquals(decision, w.previousStep(finishTask));
    }

    @Test
    public void testCurrentActor() throws WikiException
    {
        // Before starting, actor should be null
        Assertions.assertNull(w.getCurrentActor());

        // After starting, actor should be GroupPrincipal Admin
        w.start();
        Assertions.assertEquals(new GroupPrincipal("Admin"), w.getCurrentActor());

        // After decision, actor should be null again
        Decision d = (Decision) w.getCurrentStep();
        d.decide(Outcome.DECISION_APPROVE);
        Assertions.assertNull(w.getCurrentActor());
    }

    @Test
    public void testHistory() throws WikiException
    {
        Assertions.assertEquals(0, w.getHistory().size());
        w.start();
        Assertions.assertEquals(2, w.getHistory().size());
        Decision d = (Decision) w.getCurrentStep();
        d.decide(Outcome.DECISION_APPROVE);
        Assertions.assertEquals(3, w.getHistory().size());
    }

    @Test
    public void testGetStartTime() throws WikiException
    {
        // Start time should be not be set until we start the workflow
        Assertions.assertEquals(Workflow.TIME_NOT_SET, w.getStartTime());
        w.start();
        Assertions.assertFalse(Workflow.TIME_NOT_SET == w.getStartTime());
        Decision d = (Decision) w.getCurrentStep();
        d.decide(Outcome.DECISION_APPROVE);
        Assertions.assertFalse(Workflow.TIME_NOT_SET == w.getStartTime());
    }

    @Test
    public void testGetEndTime() throws WikiException
    {
        // End time should be not set until we finish all 3 steps
        Assertions.assertEquals(Workflow.TIME_NOT_SET, w.getEndTime());
        w.start();
        Assertions.assertEquals(Workflow.TIME_NOT_SET, w.getEndTime());
        Decision d = (Decision) w.getCurrentStep();
        d.decide(Outcome.DECISION_APPROVE);
        Assertions.assertFalse(Workflow.TIME_NOT_SET == w.getEndTime());
    }

    @Test
    public void testIsCompleted() throws WikiException
    {
        // Workflow isn't completed until we finish all 3 steps
        Assertions.assertFalse(w.isCompleted());
        w.start();
        Assertions.assertFalse(w.isCompleted());
        Decision d = (Decision) w.getCurrentStep();
        d.decide(Outcome.DECISION_APPROVE);
        Assertions.assertTrue(w.isCompleted());
    }

    @Test
    public void testIsStarted() throws WikiException
    {
        Assertions.assertFalse(w.isStarted());
        w.start();
        Assertions.assertTrue(w.isStarted());
    }

    @Test
    public void testStartTwice() throws WikiException
    {
        w.start();
        try
        {
            w.start();
        }
        catch (IllegalStateException e)
        {
            // Swallow
            return;
        }
        // We should never get here
        Assertions.fail("Workflow allowed itself to be started twice!");
    }

    @Test
    public void testSetId()
    {
        Assertions.assertEquals(Workflow.ID_NOT_SET, w.getId());
        w.setId(1001);
        Assertions.assertEquals(1001, w.getId());
    }

}
