/*
 This file is part of GNUnet.
 (C) 2011, 2012 Christian Grothoff (and other contributing authors)

 GNUnet is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published
 by the Free Software Foundation; either version 3, or (at your
 option) any later version.

 GNUnet is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GNUnet; see the file COPYING.  If not, write to the
 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.
 */

package org.gnunet.testing;

import com.google.common.base.Charsets;
import org.gnunet.util.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
 * Handle to a GNUnet subsystem that has been started for testing purposes.
 *
 * @author Florian Dold
*/
public class TestingSubsystem {
    private static final Logger logger = LoggerFactory
            .getLogger(TestingSubsystem.class);


    private Process p;
    private BufferedReader reader;
    private OutputStreamWriter writer;
    private Configuration cfg;

    public Configuration getConfiguration() {
        return cfg;
    }

    public TestingSubsystem(String service) {
        this(service, null);
    }

    public TestingSubsystem(String service, String configFilename) {
        final String[] args;
        if (configFilename == null) {
            args = new String[]{"gnunet-testing", "-r", service};
        } else {
            args = new String[]{"gnunet-testing", "-r", service, "-c", configFilename};
        }
        try {
            p = Runtime.getRuntime().exec(args);
        } catch (IOException e) {
            throw new TestingSetup.SetupException(e);
        }

        reader = new BufferedReader(new InputStreamReader(p.getInputStream(), Charsets.UTF_8));

        writer = new OutputStreamWriter(p.getOutputStream(), Charsets.UTF_8);

        String started;
        try {
            started = reader.readLine();
        } catch (IOException e) {
            throw new TestingSetup.SetupException(e);
        }

        if (started == null || !started.equals("ok")) {
            throw new TestingSetup.SetupException("could not start service ('" + started + "')");
        }

        String cfgFileName;
        try {
            cfgFileName = reader.readLine();
        } catch (IOException e) {
            throw new TestingSetup.SetupException(e);
        }

        if (cfgFileName == null) {
            throw new TestingSetup.SetupException("could not start subsystem for testing: no config file received from helper");
        }

        cfg = new Configuration();
        cfg.parse(cfgFileName);
    }

    public void destroy() {
        try {
            writer.write("q\n");
            writer.flush();
        } catch (IOException e) {
            throw new TestingSetup.SetupException(e);
        }
        try {
            p.waitFor();
        } catch (InterruptedException e) {
            throw new TestingSetup.SetupException(e);
        }
        if (p.exitValue() != 0) {
            throw new TestingSetup.SetupException("gnunet-testing exit value unsuccessful");
        }
    }

    public void restart() {
        try {
            writer.write("r\n");
            writer.flush();
        } catch (IOException e) {
            throw new TestingSetup.SetupException(e);
        }
        String response;
        logger.debug("waiting for gnunet-testing to respond to restart");
        try {
            response = reader.readLine();
        } catch (IOException e) {
            throw new TestingSetup.SetupException(e);
        }
        if (response == null || !response.equals("restarted")) {
            throw new TestingSetup.SetupException("wrapper did not cooperate");
        }
        logger.debug("restart successful");
    }
}
