/*
 * 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.commons.scxml2;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.apache.commons.scxml2.env.SimpleDispatcher;
import org.apache.commons.scxml2.env.Tracer;
import org.apache.commons.scxml2.io.SCXMLReader;
import org.apache.commons.scxml2.io.SCXMLReader.Configuration;
import org.apache.commons.scxml2.model.CustomAction;
import org.apache.commons.scxml2.model.EnterableState;
import org.apache.commons.scxml2.model.SCXML;
import org.apache.commons.scxml2.model.TransitionTarget;
import org.junit.jupiter.api.Assertions;

/**
 * Helper methods for running SCXML unit tests.
 */
public class SCXMLTestHelper {

    /**
     * Serialized Commons SCXML object model temporary store.
     * Assumes the default build artifacts are generated in the
     * "target" directory (so it can be removed via a clean build).
     */
    public static final String SERIALIZATION_DIR = "target/serialization";
    public static final String SERIALIZATION_FILE_PREFIX = SERIALIZATION_DIR + "/scxml";
    public static final String SERIALIZATION_FILE_SUFFIX = ".ser";

    // Generate a unique sequence number for the serialization files
    private static int sequence=0;

    private synchronized static String getSequenceNumber() {
        return Integer.toString(++sequence);
    }

    public static URL getResource(String name) {
        return SCXMLTestHelper.class.getClassLoader().getResource(name);
    }

    public static SCXML parse(final String scxmlResource) throws Exception {
        Assertions.assertNotNull(scxmlResource);
        return parse(getResource(scxmlResource), null);
    }

    public static SCXML parse(final URL url) throws Exception {
        return parse(url, null);
    }

    public static SCXML parse(final String scxmlResource, final List<CustomAction> customActions) throws Exception {
        Assertions.assertNotNull(scxmlResource);
        return parse(getResource(scxmlResource), customActions);
    }

    public static SCXML parse(final URL url, final List<CustomAction> customActions) throws Exception {
        Assertions.assertNotNull(url);
        Configuration configuration = new Configuration(null, null, customActions);
        SCXML scxml = SCXMLReader.read(url, configuration);
        Assertions.assertNotNull(scxml);
        return testModelSerializability(scxml);
    }

    public static SCXML parse(final Reader scxmlReader, final List<CustomAction> customActions) throws Exception {
        Assertions.assertNotNull(scxmlReader);
        Configuration configuration = new Configuration(null, null, customActions);
        SCXML scxml = SCXMLReader.read(scxmlReader, configuration);
        Assertions.assertNotNull(scxml);
        return testModelSerializability(scxml);
    }

    public static SCXMLExecutor getExecutor(final URL url) throws Exception {
        return getExecutor(parse(url), null);
    }

    public static SCXMLExecutor getExecutor(final String scxmlResource) throws Exception {
        return getExecutor(parse(scxmlResource), null);
    }

    public static SCXMLExecutor getExecutor(final SCXML scxml) throws Exception {
        return getExecutor(scxml, null);
    }

    public static SCXMLExecutor getExecutor(final URL url, final Evaluator evaluator) throws Exception {
        return getExecutor(parse(url), evaluator);
    }

    public static SCXMLExecutor getExecutor(final SCXML scxml, final Evaluator evaluator) throws Exception {
        return getExecutor(scxml, evaluator, new SimpleDispatcher());
    }

    public static SCXMLExecutor getExecutor(final SCXML scxml, final Evaluator evaluator, final EventDispatcher eventDispatcher) throws Exception {
        Tracer trc = new Tracer();
        SCXMLExecutor exec = new SCXMLExecutor(evaluator, eventDispatcher, trc);
        exec.setStateMachine(scxml);
        exec.addListener(scxml, trc);
        return exec;
    }

    public static TransitionTarget lookupTransitionTarget(SCXMLExecutor exec, String id) {
        return exec.getStateMachine().getTargets().get(id);
    }

    public static Context lookupContext(SCXMLExecutor exec, String id) {
        TransitionTarget tt = lookupTransitionTarget(exec, id);
        if (tt == null || !(tt instanceof EnterableState)) {
            return null;
        }
        return exec.getSCInstance().lookupContext((EnterableState)tt);
    }

    public static void assertState(SCXMLExecutor exec, String expectedStateId) {
        Set<EnterableState> currentStates = exec.getStatus().getStates();
        Assertions.assertEquals(1, currentStates.size(),
                "Expected 1 simple (leaf) state with id '" + expectedStateId +
                        "' but found " + currentStates.size() + " states instead.");
        Assertions.assertEquals(expectedStateId, currentStates.iterator().
            next().getId());
    }

    public static Set<EnterableState> fireEvent(SCXMLExecutor exec, String name) throws Exception {
        return fireEvent(exec, name, null);
    }

    public static Set<EnterableState> fireEvent(SCXMLExecutor exec, String name, Object data) throws Exception {
        TriggerEvent[] evts = {new EventBuilder(name, TriggerEvent.SIGNAL_EVENT).data(data).build()};
        exec.triggerEvents(evts);
        return exec.getStatus().getStates();
    }

    public static Set<EnterableState> fireEvent(SCXMLExecutor exec, TriggerEvent te) throws Exception {
        exec.triggerEvent(te);
        return exec.getStatus().getStates();
    }

    public static Set<EnterableState> fireEvents(SCXMLExecutor exec, TriggerEvent[] evts) throws Exception {
        exec.triggerEvents(evts);
        return exec.getStatus().getStates();
    }

    public static void assertPostTriggerState(SCXMLExecutor exec,
            String triggerEventName, String expectedStateId) throws Exception {
        assertPostTriggerState(exec, triggerEventName, null, expectedStateId);
    }

    public static void assertPostTriggerState(SCXMLExecutor exec,
            String triggerEventName, Object data, String expectedStateId) throws Exception {
        assertPostTriggerState(exec, new EventBuilder(triggerEventName, TriggerEvent.SIGNAL_EVENT)
                .data(data).build(), expectedStateId);
    }

    public static void assertPostTriggerStates(SCXMLExecutor exec,
            String triggerEventName, String[] expectedStateIds) throws Exception {
        assertPostTriggerStates(exec, triggerEventName, null, expectedStateIds);
    }

    public static void assertPostTriggerStates(SCXMLExecutor exec,
            String triggerEventName, Object data, String[] expectedStateIds) throws Exception {
        assertPostTriggerStates(exec, new EventBuilder(triggerEventName, TriggerEvent.SIGNAL_EVENT)
                .data(data).build(), expectedStateIds);
    }

    public static void assertPostTriggerState(SCXMLExecutor exec,
            TriggerEvent triggerEvent, String expectedStateId) throws Exception {
        Set<EnterableState> currentStates = fireEvent(exec, triggerEvent);
        Assertions.assertEquals(1, currentStates.size(),
                "Expected 1 simple (leaf) state with id '"
                        + expectedStateId + "' on firing event " + triggerEvent
                        + " but found " + currentStates.size() + " states instead.");
        Assertions.assertEquals(expectedStateId, currentStates.iterator().
            next().getId());
    }

    public static void assertPostTriggerStates(SCXMLExecutor exec,
            TriggerEvent triggerEvent, String[] expectedStateIds) throws Exception {
        if (expectedStateIds == null || expectedStateIds.length == 0) {
            Assertions.fail("Must specify an array of one or more "
                + "expected state IDs");
        }
        Set<EnterableState> currentStates = fireEvent(exec, triggerEvent);
        int n = expectedStateIds.length;
        Assertions.assertEquals(n, currentStates.size(),
                "Expected " + n + " simple (leaf) state(s) "
                        + " on firing event " + triggerEvent + " but found "
                        + currentStates.size() + " states instead.");
        List<String> expectedStateIdList = new ArrayList<>(Arrays.asList(expectedStateIds));
        for (TransitionTarget tt : currentStates) {
            String stateId = tt.getId();
            if(!expectedStateIdList.remove(stateId)) {
                Assertions.fail("Expected state with id '" + stateId
                    + "' in current states on firing event "
                    + triggerEvent);
            }
        }
        Assertions.assertEquals(0, expectedStateIdList.size(),
                "More states in current configuration than those"
                        + "specified in the expected state ids '" + Arrays.toString(expectedStateIds) + "'");
    }

    public static SCXML testModelSerializability(final SCXML scxml) throws Exception {
        File fileDir = new File(SERIALIZATION_DIR);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        String filename = SERIALIZATION_FILE_PREFIX
            + getSequenceNumber() + SERIALIZATION_FILE_SUFFIX;
        SCXML roundtrip;
        ObjectOutputStream out =
            new ObjectOutputStream(new FileOutputStream(filename));
        out.writeObject(scxml);
        out.close();
        ObjectInputStream in =
            new ObjectInputStream(new FileInputStream(filename));
        roundtrip = (SCXML) in.readObject();
        in.close();
        return roundtrip;
    }

    public static SCXMLExecutor testInstanceSerializability(final SCXMLExecutor exec) throws Exception {
        File fileDir = new File(SERIALIZATION_DIR);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        String filename = SERIALIZATION_FILE_PREFIX
            + getSequenceNumber() + SERIALIZATION_FILE_SUFFIX;
        ObjectOutputStream out =
            new ObjectOutputStream(new FileOutputStream(filename));
        out.writeObject(exec.detachInstance());
        out.close();
        ObjectInputStream in =
            new SCInstanceObjectInputStream(new FileInputStream(filename));
        exec.attachInstance((SCInstance) in.readObject());
        in.close();
        return exec;
    }

    /**
     * Discourage instantiation.
     */
    private SCXMLTestHelper() {
    }
}
