/**
 * Copyright (C) 2014 SINTEF <franck.fleurey@sintef.no>
 *
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3, 29 June 2007;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.gnu.org/licenses/lgpl-3.0.txt
 *
 * 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.thingml.compilers.c.arduino;

import org.thingml.compilers.ThingMLCompiler;
import org.thingml.compilers.c.CCompilerContext;

import java.util.ArrayList;
import org.sintef.thingml.Configuration;
import org.sintef.thingml.Instance;
import org.sintef.thingml.Message;
import org.sintef.thingml.Port;
import org.sintef.thingml.Thing;
import org.sintef.thingml.ThingMLModel;
import org.sintef.thingml.constraints.ThingMLHelpers;

/**
 * Created by ffl on 11.06.15.
 */
public class CCompilerContextArduino extends CCompilerContext {

    public CCompilerContextArduino(ThingMLCompiler c) {
        super(c);
    }

    public boolean sync_fifo() {
        return false;
    }

    public int fifoSize() {
        return 256;
    }

    @Override
    public void writeGeneratedCodeToFiles() {

        // COMBINE ALL THE GENERATED CODE IN A SINGLE PDE FILE

        ArrayList<String> headers = new ArrayList<String>();
        ArrayList<String> modules = new ArrayList<String>();
        String main = getCurrentConfiguration().getName() + "_cfg.c";

        for (String filename : generatedCode.keySet()) {
            if (filename.endsWith(".h")) {
                headers.add(filename);
                //System.out.println("Adding " + filename + " to headers");
            }
            if (filename.endsWith(".c") && !filename.equals(main)) {
                modules.add(filename);
                //System.out.println("Adding " + filename + " to modules");
            }
        }

        StringBuilder pde = new StringBuilder();

        for (String f : headers) {
            pde.append(generatedCode.get(f).toString());
        }

        for (String f : modules) {
            pde.append(generatedCode.get(f).toString());
        }

        pde.append(generatedCode.get(main).toString());

        //writeTextFile(getCurrentConfiguration().getName() + ".pde", pde.toString());
        writeTextFile(getCurrentConfiguration().getName() + ".ino", pde.toString());

    }
    
    @Override
    public void generatePSPollingCode(Configuration cfg, StringBuilder builder) {
        ThingMLModel model = ThingMLHelpers.findContainingModel(cfg);

        // FIXME: Extract the arduino specific part bellow

        Thing arduino_scheduler = null;
        for (Thing t : model.allThings()) {
            if (t.getName().equals("ThingMLScheduler")) {
                arduino_scheduler = t;
                break;
            }
        }
        if (arduino_scheduler != null) {
            Message poll_msg = null;
            for (Message m : arduino_scheduler.allMessages()) {
                if (m.getName().equals("poll")) {
                    poll_msg = m;
                    break;
                }
            }

            if (poll_msg != null) {
                // Send a poll message to all components which can receive it
                for (Instance i : cfg.allInstances()) {
                    for (Port p : i.getType().allPorts()) {
                        if (p.getReceives().contains(poll_msg)) {
                            builder.append(this.getHandlerName(i.getType(), p, poll_msg) + "(&" + this.getInstanceVarName(i) + ");\n");
                        }
                    }
                }

            }
        }
    }


}

@@ -667,16 +667,99 @@
 duino;%0A%0A
+import org.sintef.thingml.*;%0Aimport org.sintef.thingml.constraints.ThingMLHelpers;%0A
 import o
@@ -877,279 +877,8 @@
 ist;
-%0Aimport org.sintef.thingml.Configuration;%0Aimport org.sintef.thingml.Instance;%0Aimport org.sintef.thingml.Message;%0Aimport org.sintef.thingml.Port;%0Aimport org.sintef.thingml.Thing;%0Aimport org.sintef.thingml.ThingMLModel;%0Aimport org.sintef.thingml.constraints.ThingMLHelpers;
 %0A%0A/*
@@ -1979,24 +1979,70 @@
 Builder();%0A%0A
+        pde.append(%22#include %3CArduino.h%3E%5Cn%22);%0A
         for 

include Arduino.h on first line