<?php

/**
 * @author Gernot Walzl
 */
class BibFile {

    function __construct($filename) {
        $this->filename = $filename;
    }

    function get_entries($filename) {
        $result = array();
        $entries = array();
        $file = fopen($filename, 'r');
        if ($file) {
            $num_braces = 0;
            $current_entry = '';
            while (!feof($file)) {
                $line = trim(fgets($file));
                if (!empty($line)) {
                    $opened = substr_count($line, '{');
                    $closed = substr_count($line, '}');
                    $num_braces += $opened - $closed;
                    if (empty($current_entry)) {
                        $current_entry = $line;
                    } else {
                        $current_entry .= ' '.$line;
                    }
                    if ($num_braces == 0) {
                        array_push($entries, $current_entry);
                        $current_entry = '';
                    }
                }
            }
            fclose($file);
        }
        foreach ($entries as $entry) {
            if (substr($entry, 0, 1) === '@') {
                array_push($result, $entry);
            }
        }
        return $result;
    }

    function get_key($str_entry) {
        $start = strpos($str_entry, '{');
        $end = strpos($str_entry, ',');
        $key = substr($str_entry, $start+1, $end-$start-1);
        return $key;
    }

    function get_type($str_entry) {
        $end = strpos($str_entry, '{');
        $type = substr($str_entry, 1, $end-1);
        $type = strtolower($type);
        return $type;
    }

    function parse($str_entry) {
        $result = array();
        $matches;
        $num_matches = preg_match_all('/,\s*\w+\s*=/', $str_entry,
                $matches, PREG_OFFSET_CAPTURE);
        for ($i = 0; $i < $num_matches; $i++) {
            $field = $matches[0][$i][0];
            $field = trim(substr($field, 1, strlen($field)-2));
            $field = strtolower($field);
            $start = $matches[0][$i][1] + strlen($matches[0][$i][0]);
            if ($i+1 < $num_matches) {
                $end = $matches[0][$i+1][1];
                $value = substr($str_entry, $start, $end-$start);
            } else {
                $value = substr($str_entry, $start, strlen($str_entry)-$start-1);
            }
            $value = trim($value);
            if (substr($value,0,1) == '{' && substr($value,-1) == '}') {
                $value = substr($value, 1, strlen($value)-2);
            }
            if (substr($value,0,1) == '{' && substr($value,-1) == '}') {
                $value = substr($value, 1, strlen($value)-2);
            }
            $result[$field] = $value;
        }
        return $result;
    }

    function to_table($entries) {
        $result = array();
        foreach($entries as $entry) {
            $key = $this->get_key($entry);
            $type = $this->get_type($entry);
            $arr_type = array();
            $arr_type['type'] = $type;
            $values = $this->parse($entry);
            $result[$key] = array_merge($arr_type, $values);
        }
        return $result;
    }

    function to_array() {
        $entries = $this->get_entries($this->filename);
        $result = $this->to_table($entries);
        return $result;
    }

    function order_by(&$table, $field, $sort_type=SORT_ASC) {
        foreach ($table as $row) {
            $keys[] = $row[$field];
        }
        array_multisort($keys, $sort_type, $table);
    }

}

/**
 * @author Gernot Walzl
 */
class BibHTML {

    function println($line) {
        echo $line."\n";
    }

    function replace_tex($text) {
        $text = str_replace('\\&', '&amp;', $text);
        $text = str_replace('--', '&ndash;', $text);
        return $text;
    }

    function replace_url($subject) {
        return preg_replace('/\\\\url{([^ ]+)}/', '<a href="$1" target="_blank">$1</a>', $subject);
    }

    function print_author($author) {
        if (substr_count($author, ' and ') > 1) {
            $author = str_replace(' and', ',', $author);
        }
        $this->println($author.'.</br />');
    }

    function print_url($url) {
        $this->println('<a href="'.$url.'" target="_blank">'.$url.'</a>.');
    }

    function print_article($entry) {
        $this->print_author($entry['author']);
        $this->println($this->replace_tex($entry['title']).'.<br />');
        print('<em>'.$this->replace_tex($entry['journal']).'</em>, ');
        if (!empty($entry['pages'])) {
            print('pages '.$this->replace_tex($entry['pages']).', ');
        }
        $this->println($this->replace_tex($entry['year']).'.<br />');
        if (!empty($entry['note'])) {
            $this->println($this->replace_url($entry['note']).'.<br />');
        }
        if (!empty($entry['url'])) {
            $this->print_url($entry['url']);
        }
    }

    function print_inproceedings($entry) {
        $this->print_author($entry['author']);
        $this->println($this->replace_tex($entry['title']).'.<br />');
        print('In <em>'.$this->replace_tex($entry['booktitle']).'</em>, ');
        if (!empty($entry['pages'])) {
            print('pages '.$this->replace_tex($entry['pages']).', ');
        }
        if (!empty($entry['address'])) {
            print($this->replace_tex($entry['address']).', ');
        }
        $this->println($this->replace_tex($entry['year']).'.<br />');
        if (!empty($entry['note'])) {
            $this->println($this->replace_url($entry['note']).'.<br />');
        }
        if (!empty($entry['url'])) {
            $this->print_url($entry['url']);
        }
    }

    function print_conference($entry) {
        $this->print_author($entry['author']);
        $this->println($this->replace_tex($entry['title']).'.<br />');
        print('<em>'.$this->replace_tex($entry['booktitle']).'</em>, ');
        if (!empty($entry['address'])) {
            print($this->replace_tex($entry['address']).', ');
        }
        $this->println($this->replace_tex($entry['year']).'.<br />');
        if (!empty($entry['note'])) {
            $this->println($this->replace_url($entry['note']).'.<br />');
        }
        if (!empty($entry['url'])) {
            $this->print_url($entry['url']);
        }
    }

    function print_incollection($entry) {
        $this->print_author($entry['author']);
        $this->println($this->replace_tex($entry['title']).'.<br />');
        $this->println('In <em>'.$this->replace_tex($entry['booktitle']).'</em>, ');
        if (!empty($entry['pages'])) {
            print('pages '.$this->replace_tex($entry['pages']).', ');
        }
        $this->println($this->replace_tex($entry['publisher']).'.<br />');
        $this->println($this->replace_tex($entry['year']).'.<br />');
        if (!empty($entry['note'])) {
            $this->println($this->replace_url($entry['note']).'.<br />');
        }
        if (!empty($entry['url'])) {
            $this->print_url($entry['url']);
        }
    }

    function print_phdthesis($entry) {
        $this->print_author($entry['author']);
        $this->println('<em>'.$this->replace_tex($entry['title']).'</em>.<br />');
        $this->println('PhD thesis, '.
            $this->replace_tex($entry['school']).', '.
            $this->replace_tex($entry['year']).'.<br />');
        if (!empty($entry['note'])) {
            $this->println($this->replace_url($entry['note']).'.<br />');
        }
        if (!empty($entry['url'])) {
            $this->print_url($entry['url']);
        }
    }

    function print_mastersthesis($entry) {
        $this->print_author($entry['author']);
        $this->println('<em>'.$this->replace_tex($entry['title']).'</em>.<br />');
        $this->println('Master\'s thesis, '.
            $this->replace_tex($entry['school']).', '.
            $this->replace_tex($entry['year']).'.<br />');
        if (!empty($entry['note'])) {
            $this->println($this->replace_url($entry['note']).'.<br />');
        }
        if (!empty($entry['url'])) {
            $this->print_url($entry['url']);
        }
    }

    function print_techreport($entry) {
        $this->print_author($entry['author']);
        $this->println('<em>'.$this->replace_tex($entry['title']).'</em>.<br />');
        $this->println('Technical report, '.
            $this->replace_tex($entry['institution']).', '.
            $this->replace_tex($entry['year']).'.<br />');
        if (!empty($entry['note'])) {
            $this->println($this->replace_url($entry['note']).'.<br />');
        }
        if (!empty($entry['url'])) {
            $this->print_url($entry['url']);
        }
    }

    function print_misc($entry) {
        $this->print_author($entry['author']);
        $this->println($this->replace_tex($entry['title']).'.<br />');
        if (!empty($entry['howpublished'])) {
            print($this->replace_tex($entry['howpublished']).', ');
        }
        $this->println($this->replace_tex($entry['year']).'.<br />');
        if (!empty($entry['note'])) {
            $this->println($this->replace_url($entry['note']).'.<br />');
        }
        if (!empty($entry['url'])) {
            $this->print_url($entry['url']);
        }
    }

    function format_label($entry) {
        $label = '';
        $authors = explode(' and ', $entry['author']);
        if (count($authors) > 1) {
            foreach ($authors as $author) {
                $names = explode(' ', $author);
                $label .= substr(end($names), 0, 1);
            }
        } else {
            $names = explode(' ', $authors[0]);
            $label .= substr(end($names), 0, 3);
        }
        $label .= substr($entry['year'], 2, 2);
        return $label;
    }

    function print_entry($cnt, $entry) {
        // $this->println('<dt>['.$cnt.']</dt>');
        $this->println('<dt>['.$this->format_label($entry).']</dt>');
        $this->println('<dd>');
        $type = $entry['type'];
        if ($type == 'article') {
            $this->print_article($entry);
        } else if ($type == 'inproceedings') {
            $this->print_inproceedings($entry);
        } else if ($type == 'conference') {
            $this->print_conference($entry);
        } else if ($type == 'incollection') {
            $this->print_incollection($entry);
        } else if ($type == 'phdthesis') {
            $this->print_phdthesis($entry);
        } else if ($type == 'mastersthesis') {
            $this->print_mastersthesis($entry);
        } else if ($type == 'techreport') {
            $this->print_techreport($entry);
        } else if ($type == 'misc') {
            $this->print_misc($entry);
        } else {
            $this->println('Warning: type='.$type);
        }
        $this->println('</dd>');
    }

    function print_entries($entries) {
        $this->println('<dl class="bibliography">');
        $cnt = 0;
        foreach ($entries as $entry) {
            if ($entry['type'] != 'comment') {
               $cnt++;
               $this->print_entry($cnt, $entry);
            }
        }
        $this->println('</dl>');
    }

}

// The variable $_path is set by the php script that includes this file.
$path = '.';
if (!empty($_path)) {
    $path = $_path;
}

$bib_file = new BibFile($path.'/publications.bib');
$entries = $bib_file->to_array();
$bib_file->order_by($entries, 'year', SORT_DESC);
$bib_html = new BibHTML();
$bib_html->print_entries($entries);

?>