#!/usr/bin/php5
<?php

function scriptEncode($m)
{
    $m[2] = urlencode($m[2]);

    return '<script'.$m[1].'>'.$m[2].'</script>';
}

function scriptSecure($m)
{
    $m[2] = str_replace(
        array('<', '>'),
        array('%inf%', '%sup%'),
        $m[2]
    );

    return '<script'.$m[1].'>'.$m[2].'</script>';
}

function scriptUnSecure($m)
{
    $m[2] = str_replace(
        array('%inf%', '%sup%'),
        array('<', '>'),
        $m[2]
    );

    return '<script'.$m[1].'>'.$m[2].'</script>';
}

function scriptDecode($m)
{
    return '<script'.$m[1].'>'.urldecode($m[2]).'</script>';
}

function styleEncode($m)
{
    $m[2] = urlencode($m[2]);

    return '<style'.$m[1].'>'.$m[2].'</style>';
}

function styleSecure($m)
{
    $m[2] = str_replace(
        array('<', '>'),
        array('%inf%', '%sup%'),
        $m[2]
    );

    return '<style'.$m[1].'>'.$m[2].'</style>';
}

function styleUnSecure($m)
{
    $m[2] = str_replace(
        array('%inf%', '%sup%'),
        array('<', '>'),
        $m[2]
    );

    return '<style'.$m[1].'>'.$m[2].'</style>';
}

function styleDecode($m)
{
    return '<style'.$m[1].'>'.urldecode($m[2]).'</style>';
}

function phpEncode($m)
{
    $m[1] = urlencode($m[1]);

    return '<?php'.$m[1].'?>';
}

function phpSecure($m)
{
    $m[1] = str_replace(
                array('<', '>'),
                array('%inf%', '%sup%'),
                $m[1]
        );

    return '<?php'.$m[1].'?>';
}

function phpUnSecure($m)
{
    $m[1] = str_replace(
                array('%inf%', '%sup%'),
                array('<', '>'),
                $m[1]
        );

    return '<?php'.$m[1].'?>';
}

function phpDecode($m)
{
    return '<?php'.urldecode($m[1]).'?>';
}

function minimize($m)
{
    if (isset($m[2], $m[3])) {
        return '<'.$m[1].$m[2].$m[3].'>'.trim($m[4]).'</'.$m[1].'>';
    }

    return '<'.$m[1].'>'.trim($m[2]).'</'.$m[1].'>';
}

function indent($str)
{
    $lines = preg_replace_callback('`<script([^>]*)>(.*)</script>`isU', 'scriptEncode', $str);
    $lines = preg_replace_callback('`<style([^>]*)>(.*)</style>`isU', 'styleEncode', $lines);
    $lines = preg_replace_callback('`<\?php(.*)\?>`isU', 'phpEncode', $lines);

    $lines = explode("\n", $lines);

    foreach ($lines as $k => $line) {
        $lines[$k] = trim($line);
        if (empty($lines[$k])) {
            unset($lines[$k]);
        }
    }

    $html = implode("\n", $lines);

    $html = preg_replace_callback('`<script([^>]*)>(.*)</script>`isU', 'scriptDecode', $html);
    $html = preg_replace_callback('`<style([^>]*)>(.*)</style>`isU', 'styleDecode', $html);
    $html = preg_replace_callback('`<\?php(.*)\?>`isU', 'phpDecode', $html);

    $html = preg_replace_callback('`<script([^>]*)>(.*)</script>`isU', 'scriptSecure', $html);
    $html = preg_replace_callback('`<style([^>]*)>(.*)</style>`isU', 'styleSecure', $html);
    $html = preg_replace_callback('`<\?php(.*)\?>`isU', 'phpSecure', $html);

    $html = str_replace("\r", '', $html);

    //$html = preg_replace_callback('`<script([^>]*)>(.*)</script>`isU', 'scriptB', $html);

    $strlen = strlen($html);
    $newhtml = '';
    $tabnum = -1;
    $auto_closed = false;

    for ($u = 0; $u < $strlen; ++$u) {
        $balise = false;

        if ($html[$u] == '<') {
            if ($html[$u + 1] == '/') {
                $newhtml .= "\n".str_repeat("\t", max(0, $tabnum--));
            } elseif ($html[$u + 1] != '!') {
                $newhtml .= "\n".str_repeat("\t", max(0, ++$tabnum));
            } elseif ($html[$u + 1] == '!') {
                $newhtml .= "\n".str_repeat("\t", max(0, $tabnum + 1));
            }

            $balise = true;

            if (
                (isset($html[$u + 1], $html[$u + 2], $html[$u + 3]) && strtolower($html[$u + 1].$html[$u + 2].$html[$u + 3]) == 'img')
                ||
                (isset($html[$u + 1], $html[$u + 2], $html[$u + 3]) && strtolower($html[$u + 1].$html[$u + 2].$html[$u + 3]) == 'col')
                ||
                (isset($html[$u + 1], $html[$u + 2], $html[$u + 3], $html[$u + 4], $html[$u + 5]) && strtolower($html[$u + 1].$html[$u + 2].$html[$u + 3].$html[$u + 4].$html[$u + 5]) == 'input')
                ||
                (isset($html[$u + 1], $html[$u + 2], $html[$u + 3], $html[$u + 4]) && strtolower($html[$u + 1].$html[$u + 2].$html[$u + 3].$html[$u + 4]) == '?xml')
                ||
                (isset($html[$u + 1], $html[$u + 2], $html[$u + 3], $html[$u + 4]) && strtolower($html[$u + 1].$html[$u + 2].$html[$u + 3].$html[$u + 4]) == 'link')
                ||
                (isset($html[$u + 1], $html[$u + 2], $html[$u + 3], $html[$u + 4]) && strtolower($html[$u + 1].$html[$u + 2].$html[$u + 3].$html[$u + 4]) == 'meta')
                ||
                (isset($html[$u + 1], $html[$u + 2], $html[$u + 3], $html[$u + 4]) && strtolower($html[$u + 1].$html[$u + 2].$html[$u + 3].$html[$u + 4]) == 'path')
                ||
                (isset($html[$u + 1], $html[$u + 2]) && strtolower($html[$u + 1].$html[$u + 2]) == 'hr')
                ||
                (isset($html[$u + 1], $html[$u + 2]) && strtolower($html[$u + 1].$html[$u + 2]) == 'br')
            ) {
                --$tabnum;
                $auto_closed = true;
            }
        }

        if (isset($html[$u - 1]) && $html[$u - 1] == "\n" && !$balise) {
            $newhtml .= str_repeat("\t", max(0, $tabnum + 1));
        }

        $newhtml .= $html[$u];

        if ($html[$u] == '>' && $html[$u - 2].$html[$u - 1] != '--') {
            if ($html[$u - 1] == '/' && !$auto_closed) {
                --$tabnum;
            }

            $newhtml .= "\n".str_repeat("\t", max(0, $tabnum + 1));
        }
    }

    /*$newhtml = str_replace(
        array('%inf%', '%sup%'),
        array('<', '>'),
        $newhtml
    );*/
    $newhtml = preg_replace_callback('`<script([^>]*)>(.*)</script>`isU', 'scriptUnSecure', $newhtml);
    $newhtml = preg_replace_callback('`<style([^>]*)>(.*)</style>`isU', 'styleUnSecure', $newhtml);
    $newhtml = preg_replace_callback('`<\?php(.*)\?>`isU', 'phpUnSecure', $newhtml);

    $newhtml = explode("\n", $newhtml);

    foreach ($newhtml as $k => $line) {
        if (trim($line) == '') {
            unset($newhtml[$k]);
        }
    }

    $newhtml = implode("\n", $newhtml);
    $newhtml = preg_replace("\n{2,}", "\n", $newhtml);

    $newhtml = preg_replace_callback('`<([^>]+)>([^<]+)</\1>`isU', 'minimize', $newhtml);
    $newhtml = preg_replace_callback('`<([^\s]+)(\s+)([^>]+)>([^<]+)</\1>`isU', 'minimize', $newhtml);

    return  $newhtml;
}

if (!isset($argv[1]) || (isset($argv[1]) && $argv[1] == '-')) {
    $handle = fopen('php://stdin', 'r');

    $code = '';

    while (!feof($handle)) {
        $code .= rtrim(fgets($handle)).PHP_EOL;
    }

    echo indent($code);
} else {
    if (file_exists($argv[1])) {
        if (preg_match('/.js(on)?$/', $argv[1])) {
            $cmd = sprintf('%s -f %s -o %s', '/usr/local/bin/js-beautify', escapeshellarg($argv[1]), escapeshellarg($argv[1]));
            $code = shell_exec($cmd);
        } elseif (preg_match('/.css$/', $argv[1])) {
            $code = shell_exec(sprintf('%s %s | sed "s/\}/\}\n/g;s/  /\t/g"', 'lessc', escapeshellarg($argv[1])));
            //$code = shell_exec(sprintf('%s %s | sed "s/\}/\}\n/g"', 'lessc', escapeshellarg($argv[1])));
            file_put_contents($argv[1], $code);
        } else {
            $code = file_get_contents($argv[1]);
            file_put_contents($argv[1], indent($code));
        }
    }
}
