#!/usr/bin/env raku

=begin pod

=head1 NAME

dfm-sql-extract - Extract SQL queries from Delphi DFM files

=head1 SYNOPSIS

dfm-sql-extract

=head1 DESCRIPTION

Parses Delphi DFM files (encoded in latin-1) and extracts all SQL.Strings
components from TUniQuery objects, saving each as an individual SQL file.

Uses a proper parser to handle nested parentheses and complex SQL statements.

=end pod

use v6.d;

use DFM::Parser;

class DFM-Extract-SQL {
  method simple-string($/)   { make ~$/<v>; }
  method hashtag-char($/)    { make chr $/<number>.Int; }
  method short-string($/)    { make [~] $/.caps.map(*.value.made); }
  method string($/)          { make $/<short-string>».made.join(''); }
  method string-list($/)     { make $/<string>».made; }

  method object($/) {
    unless $/<classname> ~~ /:i query$/ {
      make [,] $/.<component>.map(*.<object>).map(*.made).flat.grep(*.so);
      return
    }
    my $id = $/<id>.Str || "qqQuery{sprintf '%05d', ++$}";

    make [ $/<component>.list.grep({.<component-name> && .<component-name> ~~ /:i sql\.strings/}).map: {
      $id => .<component-value><string-list>.made
    } ]

    # ; say "[ $id ]\n{ $/.made.raku }";# exit
  }
  method TOP($/) { make $/.<object>.made }
}

sub parse-dfm(IO() $_ where *.open) {
  state DFM-Extract-SQL $actions .= new;
  DFM::Parser.parse($_.slurp, :$actions).made
}

sub rmrf(IO $_) {
  if .d {
    .dir.map({ .IO.&rmrf unless /^\.\.?$/ });
    .rmdir
  } elsif .f {
    .unlink
  } 
}

sub MAIN(*@file-names, IO() :$output = $*TMPDIR) {
  my @parsed-files = @file-names.map: {
    $output.add(.IO.absolute.IO.extension('')) => .&parse-dfm
  }

  for @parsed-files {
    next unless .value;
    my $dd = .key.IO.mkdir;
    say "--  FILENAME {.key}";
    for .value {
      say "--  QUERY {.key}";
      $dd.add("{.key}.sql").spurt: .value.join("\n")
    }
  }
}

