/**
 * Licensed 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.
 *
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 */
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.thingml.compilers.checker.genericRules;

import org.eclipse.emf.ecore.util.EcoreUtil;
import org.thingml.compilers.checker.Checker;
import org.thingml.compilers.checker.Checker.InfoType;
import org.thingml.compilers.checker.Rule;
import org.thingml.xtext.constraints.ThingMLHelpers;
import org.thingml.xtext.helpers.AnnotatedElementHelper;
import org.thingml.xtext.thingML.CompositeState;
import org.thingml.xtext.thingML.Configuration;
import org.thingml.xtext.thingML.FinalState;
import org.thingml.xtext.thingML.State;
import org.thingml.xtext.thingML.Thing;
import org.thingml.xtext.thingML.ThingMLModel;

/**
 *
 * @author sintef
 */
public class StatesUsage extends Rule {

    public StatesUsage() {
        super();
    }

    @Override
    public InfoType getHighestLevel() {
        return InfoType.NOTICE;
    }

    @Override
    public String getName() {
        return "Things Usage";
    }

    @Override
    public String getDescription() {
        return "Check for sink and unreachable states.";
    }

    @Override
    public void check(ThingMLModel model, Checker checker) {
        for (Thing t : ThingMLHelpers.allThings(model)) {
            check(t, checker);
        }
    }

    @Override
    public void check(Configuration cfg, Checker checker) {
        for (Thing t : ThingMLHelpers.allThings(ThingMLHelpers.findContainingModel(cfg))) {
            check(t, checker);
        }
    }

    private void check(Thing t, Checker checker) {
        for (CompositeState sm : ThingMLHelpers.allStateMachines(t)) {
            for (State s : org.thingml.xtext.helpers.StateHelper.allStates(sm)) {
                if((EcoreUtil.equals(s, sm)))
                    continue;
                if (!AnnotatedElementHelper.isDefined(s, "SuppressWarnings", "Unreachable")) {
                    //TODO: Re-implement the unreachable condition
                	/*
                	if (s.getIncoming().size() == 0 && !EcoreUtil.equals(s, sm.getInitial()) && !EcoreUtil.equals(s, sm)) {
                        checker.addGenericNotice("Unreachable state " + s.getName() + " in Thing " + t.getName() + ".", s);
                    }
                    */
                }
                if (!AnnotatedElementHelper.isDefined(s, "SuppressWarnings", "Sink")) {
                    if (!(s instanceof FinalState) && !(((CompositeState)s.eContainer()).getSubstate().size() == 1) && s.getOutgoing().size() == 0 && !EcoreUtil.equals(s, sm)) {
                        checker.addGenericNotice("Sink state " + s.getName() + " in Thing " + t.getName() + ".", s);
                    }
                }
            }
        }
    }

}

@@ -1851,23 +1851,72 @@
 eck 
-for sink and un
+that a thing has no more than one state machine, that state are 
 reac
@@ -1924,16 +1924,13 @@
 able
- states.
+, etc
 %22;%0A 
@@ -2326,24 +2326,24 @@
    %7D%0A    %7D%0A%0A
-
     private 
@@ -2373,32 +2373,558 @@
 cker checker) %7B%0A
+    %09if (ThingMLHelpers.allStateMachines(t).size() %3E 1) %7B%0A    %09%09String msg = %22Thing %22 + t.getName() + %22 has multiple state machines: %22;%0A    %09%09int i = 0;%0A    %09%09for(CompositeState sm : ThingMLHelpers.allStateMachines(t)) %7B%0A    %09%09%09if (i %3E 0)%0A    %09%09%09%09msg += %22, %22;%0A    %09%09%09msg += ((Thing)sm.eContainer()).getName() + %22:%22 + sm.getName(); %0A    %09%09%09i++;%0A    %09%09%7D%0A    %09%09msg += %22.%5CnMake sure one and only state machine is defined in the context of Thing %22 + t.getName();%0A            checker.addGenericError(msg, t);    %09%09%0A    %09%7D    %09    %09%0A
         for (Com

check that a Thing has almost one statechart