<?php

namespace EGabrielse;

// Go up to root of plugin require_once dirname(dirname(dirname(dirname(__DIR__)))) . “/vendor/autoload.php”;

use MtHaml; use MichelfMarkdown as Markdown; use CoffeeScriptCompiler as CoffeeScript;

/**

* Compile Haml files locally. Used during development stages.
*   Can minify compiled assets for production, as well as
*   compile inline Markdown and CoffeeScript.
*
* @since 0.1.0
*/

class MtHamlCompiler {

/**
 * @var {String}
 *   Input filename that was passed into compiler
 *
 * @since 0.1.0
 */
private $input_file;

/**
 * @var {String}
 *   Output directory to write compiled output to
 *
 * @since 0.1.0
 */
private $output_dir;

/**
 * @var {String}
 *   Type of MtHaml environment, either Twig or PHP
 *
 * @since 0.1.0
 */
private $environment;

/**
 * @var {String}
 *   Extension of output file
 *
 * @since 0.3.0
 */
private $extension;

/**
 * @var {Array}
 *   Array of options to be passed to MtHaml
 *
 * @since 0.1.0
 */
private $options;

/**
 * @var {Array}
 *   Array containing Haml filters and their instances
 *
 * @since 0.1.0
 */
private $filters;

/**
 * @var {Object}
 *   Instance of \MtHaml\Support\Php\Executor used to compile static files
 *
 * @since 0.1.0
 */
private $executor;

/**
 * @var {Object}
 *   Instance of \MtHaml\Environment used to compile files
 *
 * @since 0.1.0
 */
private $compiler;

/**
 * @var {String}
 *   Compiled output of Haml file
 *
 * @since 0.1.0
 */
private $output;

/**
 * Constructor
 *
 * @param {Array} $opts
 *   Array that contains input file and output directory
 *
 * @since 0.1.0
 */
public function __construct( $opts = array() ) {

    // Set filters
    $this->filters["markdown"] = new \MtHaml\Filter\Markdown\MichelfMarkdown( new Markdown );
    $this->filters["coffeescript"] = new \MtHaml\Filter\CoffeeScript( new CoffeeScript(), array( "header" => false ) );

    /**
     * Get the input file
     */
    if( isset( $opts['input'] ) ) {
        $this->input_file = $opts['input'];
    } else {
        throw new \Exception( self::colorize( "No input file was passed into \$opts.", ";31" ) );
    }

    /**
     * Get the output dir
     */
    if( isset( $opts['output'] ) ) {
        $this->output_dir = $opts["output"];
    } else {
        throw new \Exception( self::colorize( "No output directory was passed into \$opts.", ";31" ) );
    }

    /**
     * Make sure an options map was passed
     */
    if( isset( $opts['options'] ) ) {
        $this->options = $opts['options'];
    } else {
        throw new \Exception( self::colorize( "No options were passed into \$opts.", ";31" ) );
    }

    /**
     * Set the environment
     */
    if( isset( $this->options['environment'] ) ) {
        $this->environment = $this->options['environment'];
    } else {
        throw new \Exception( self::colorize( "No environment was passed into \$opts.", ";31" ) );
    }

    /**
     * Set the output extension
     */
    if( isset( $this->options['extension'] ) ) {
        $this->extension = $this->options['extension'];
    } else {
        $this->extension = $this->environment;
    }

    // Set the MtHaml environment
    self::set_environment();
}

/**
 * Colorize output messages to terminal
 *
 * @param {String} $message
 * @param {String} $color
 *
 * @since 0.2.0
 */
public static function colorize($message, $color) {
    return "\e[0$color" . "m" . "$message\e[0m";
}

/**
 * Runs compiler and writes contents to output file
 *
 * @since 0.1.0
 */
public function run() {
    // Compile output
    $this->output = $this->compile();
    // Compress output if set
    if( $this->options["compress_output"] ) {
        $this->output = $this->compress();
    }
    // Write output to file
    $this->write();
}

/**
 * Create HtHaml environment
 *
 * @since 0.1.0
 */
private function set_environment() {
    $this->compiler = new \MtHaml\Environment( $this->environment, array(
        'enable_dynamic_attrs' => false,
        "enable_escaper" => false,
        "cdata" => false
    ), array(
        "markdown" => $this->filters["markdown"],
        "coffeescript" => $this->filters["coffeescript"],
    ));
}

/**
 * Instantiate MtHaml and compile passed file
 *
 * @since 0.1.0
 */
private function compile() {
    if ( $this->options["static_files"] ) {
        // Instantiate executor based on environment
        if ( $this->environment == "php" ) {
            $this->executor = new \MtHaml\Support\Php\Executor( $this->compiler, array(
                "cache" => $this->output_dir . '/cache',
            ));
        } else {
            throw new \Exception(self::colorize( "To compile static files, please set your environment to PHP. It is currently set to `$this->environment`.", ";31" ) );
        }
        // Compile assets
        return $this->executor->render( $this->input_file, array() );
    } else {
        // Get contents from input file and compile
        return $this->compiler->compileString( file_get_contents( $this->input_file ), basename( $this->input_file ) );
    }
}

/**
 * Removes all white space and newlines from output
 *
 * @TODO Find a Composer plugin that will do this, as this isn't very clean
 *
 * @since 0.1.0
 */
private function compress() {
    return preg_replace( "/^\s+|\n|\r|\s+$/m", "", $this->output );
}

/**
 * Make sure that the path is writable
 *
 * @param {String} $dir
 *   Directory path
 *
 * @since 0.1.0
 */
private function ensure_path_writable( $dir ) {
    // Attempt to change permissions if not writable
    if ( ! is_writable( $dir ) ) {
        chmod( $dir, 0760 );
    }
    // If dir is still not writable, throw err
    if ( ! is_writable( $dir ) ) {
        throw new \Exception( self::colorize( "It looks like the directory `$dir` isn't writable.", ";31" ) );
    }
}

/**
 * Writes compiled assets to output file
 *
 * @since 0.1.0
 */
private function write() {
    if ( $this->output ) {
        // Make sure our path is writable
        self::ensure_path_writable( $this->output_dir );
        // Render output
        return file_put_contents( "$this->output_dir/" . basename( $this->input_file, ".haml" ) . ".$this->extension", $this->output );
    } else {
        throw new \Exception( self::colorize( "It looks like `" . basename( $this->input_file ) . "` compiled without any output.", ";33" ) );
    }
}

}

/**

* Get passed arguments from Guard
*/

$opts = getopt( “”, array( “input:”, “output:”, “environment:”, “static_files:”, “compress_output:”, “extension:” ) );

/**

* Instantiate compiler and parse file with input from Guard
*/

try {

$compiler = new MtHamlCompiler( array(
    "input" => $opts["input"],
    "output" => $opts["output"],
    "options" => array(
        "environment" => $opts["environment"],
        "extension" => $opts["extension"],
        "static_files" => $opts["static_files"] === "true" ? true : false,
        "compress_output" => $opts["compress_output"] === "true" ? true : false
    )
));
$compiler->run();

} catch ( Exception $err ) {

fwrite( STDERR, "Guard::MtHaml - " . MtHamlCompiler::colorize( $err->getMessage() . "\n", ";31" ) );
exit(1);

}