#!/usr/bin/perl
package IkiWiki::Plugin::new_org;

use warnings;
use strict;
use IkiWiki 3.00;
use File::Temp qw/ tempfile unlink0 /;

my $org_file_regexp = qr/\.org$/;

# No output to stdout in CGI mode. In other modes, we want it for
# debugging.
my $redir = ($ENV{REQUEST_METHOD} ? " > /dev/null" : "");

sub systemr($) {
    my $cmd = shift;
    system($cmd . $redir);
}

sub run_func_in_emacs($$;$) {
    my $func = shift;
    my $content = shift;
    my $args = shift;
    my ($tf1, $tn1) = tempfile("/tmp/ikiwiki-org-1-XXXXX"); # Perl output, emacs input
    my ($tf2, $tn2) = tempfile("/tmp/ikiwiki-org-2-XXXXX"); # Perl input, emacs output
    binmode($tf1, ":utf8");
    binmode($tf2, ":utf8");
    print $tf1 $content;
    if (!defined $args) { $args = ""; }
    # WARNING: possible security hole
    $args =~ s/'/'\\''/g;
    systemr(qq/unset ALTERNATE_EDITOR; emacsclient -s org-ikiwiki-compiler --eval '(ikiwiki-org-$func "$tn1" "$tn2" $args)'/);
#     my $el = $INC{'IkiWiki/Plugin/new_org.pm'} =~ s/new_org\.pm$/ikiwiki-org-plugin.el/r;
#     systemr(qq#emacs -q -Q --eval "(add-to-list 'load-path \\"/usr/share/emacs/site-lisp/org-mode\\")" --load $el --batch --eval '(ikiwiki-org-$func "$tn1" "$tn2" $args)'#);
    my @ret = <$tf2>;
    unlink0($tf1, $tn1);
    unlink0($tf2, $tn2);
    return @ret;
}

sub import {
    systemr("unset ALTERNATE_EDITOR; emacsclient -s org-ikiwiki-compiler --eval nil");
    if ($? != 0) {
	my $el = $INC{'IkiWiki/Plugin/new_org.pm'} =~ s/new_org\.pm$/ikiwiki-org-plugin.el/r;
	my $repo_root = $INC{'IkiWiki/Plugin/new_org.pm'} =~ s,libdir/IkiWiki/Plugin/new_org.pm$,,r;
	systemr("nix run $repo_root#emacs -- -Q --daemon=org-ikiwiki-compiler --load $el");
	if ($? != 0) {
	    print STDERR "Failed to start emacs. Will not continue with new_org setup.\n";
	    return;
	}
    }
    hook(type => "htmlize", id => "org", call => \&htmlize, first => 1);
    hook(type => "linkify", id => "org", call => \&linkify, first => 1);
    hook(type => "scan", id => "org", call => \&scan);
}

sub linkify(@) {
    my %params = @_;
    my $page = $params{page};
    my $page_file_name = $pagesources{$page};

    return $params{content} unless $page_file_name =~ $org_file_regexp;

    my $hash_adds = "";
    foreach my $link (@{$links{$page}}) {
	my $bp = bestlink($page, $link);
	if ($bp) {
	    $hash_adds .= qq/ (puthash "$link" "$bp" page-hash)/;
	}
    }
    my $page_hash = "(let ((page-hash (make-hash-table :test 'equal))) $hash_adds page-hash)";
    return join('', run_func_in_emacs("linkify", $params{content}, "\"$params{destpage}\" $page_hash"));
}

my $url_regexp = qr/^(?:[^:]+:\/\/|mailto:).*/i;

# Store info about page title, authors and links to other pages.
sub scan(@) {
    my %params = @_;
    my $page = $params{page};
    my $page_file_name = $pagesources{$page};

    return unless $page_file_name =~ $org_file_regexp;

    my @lines = run_func_in_emacs("scan", $params{content});
    foreach my $line (@lines) {
	chomp $line;
	if ($line =~ /#\+TITLE: (.*)$/) {
	    $pagestate{$params{page}}{meta}{title} = $1;
# 	} elsif ($line =~ /#\+AUTHOR: (.*)$/) {
# 	    $pagestate{$params{page}}{meta}{author} = $1;
	} else {
	    add_link($params{page}, $line);
	}
    }
}

sub htmlize(@) {
    my %params = @_;
    return join('', run_func_in_emacs("htmlize", $params{content}));
}

1;
