#!/usr/bin/perl -w
####################################################################################################
#
# Helper script for Qt 5
#
# Copyright (C) 2015 The Qt Company Ltd.
# Contact: http://www.qt.io/licensing/
#
####################################################################################################

############################################################################################
#
# Generates the source files ui4.cpp, ui4.h used in the uic tool, the QtUiTools library and
# Qt Designer from the XML schema used for .ui files.
#
############################################################################################

use strict;

use File::Basename;
use File::Spec;
use File::Copy;
use IO::File;
use File::Path;
use File::Temp;

my $USAGE=<<EOF;
Usage: generate_ui

Generates the source files ui4.cpp, ui4.h used in the uic tool, the QtUiTools library and
Qt Designer from the XML schema used for .ui files.

Requires the environment variable QTDIR to point to qtbase and xalan.
EOF

my $qtDir = $ENV{'QTDIR'};
die ('QTDIR not set') unless defined $qtDir && -d $qtDir;

print 'Generating ui4.cpp/ui4.h ',$qtDir,"\n";

my $uicDir =  File::Spec->catfile($qtDir, 'src', 'tools', 'uic');
my $toolsDir = File::Spec->catfile($qtDir, '..', 'qttools');
my $designerDir = File::Spec->catfile($toolsDir, 'src', 'designer');
my $uiLibDir = File::Spec->catfile($designerDir, 'src', 'lib', 'uilib');
my $xmlDir = File::Spec->catfile($designerDir, 'data');
my $qtXmlPatterns = File::Spec->catfile($qtDir, 'bin', 'xmlpatterns');

print 'uic at: ',$uicDir, ' Designer at: ',$designerDir, ' uilib at: ',$uiLibDir,' XML at ',$xmlDir,"\n";
die ('Invalid folder structure') unless -d $xmlDir && -d $uicDir && -d $uiLibDir;

# Read out license delimited by '/** .. **/' from a C++ source
sub readCppLicense
{
    my ($fileName) = @_;
    my $license = '';
    my $file = new IO::File('<' . $fileName) or die ('Unable to open ' . $fileName . ' for reading: ' . $!);
    while (my $line = <$file>) {
        $license .= $line;
        last if index($line, '*****/') >= 0;
    }
    $file->close();
    return $license;
}

# Replace special keys in XSL files and return a handle to temporary file
sub replaceXslKeys
{
   my ($xslSourceFileName, $license, $uiHeaderName) = @_;

   my $xslSourceFile = new IO::File('<' . $xslSourceFileName) or die ('Unable to open ' . $xslSourceFileName . ' for reading: ' . $!);
   my $xsl = '';
   while (my $line = <$xslSourceFile>) {
       $xsl .= $line;
   }
   $xslSourceFile->close();
   $xsl =~ s/\@LICENSE\@/$license/g;
   $xsl =~ s/\@HEADER\@/$uiHeaderName/g if defined $uiHeaderName;

   my $xslHandle = File::Temp->new(DIR => dirname($xslSourceFileName), SUFFIX => '.xsl');
   print $xslHandle $xsl;
   $xslHandle->close();
   return $xslHandle;
}

# Run xalan. Note: xmlpatterns currently reports a syntax error on the sheets
sub runXSLT
{
   my ($source, $sheet, $target) = @_;
   my $rc = system('xalan', '-in', $source, '-xsl',  $sheet, '-out', $target);
#   my $rc = system($qtXmlPatterns, '-output', $target, $sheet, $source);
   die ('Xalan failed on ' . $source . ' ' . $sheet) unless $rc == 0;
}

# Generate uilib header and source.

my $uiLibImpl = File::Spec->catfile($uiLibDir, 'ui4.cpp');
my $uiLibHeader = File::Spec->catfile($uiLibDir, 'ui4_p.h');
my $license = readCppLicense($uiLibImpl);

print "Running XSLT processor for uilib header...\n";

my $ui4Xsd = File::Spec->catfile($xmlDir, 'ui4.xsd');
my $headerXslSource = File::Spec->catfile($xmlDir, 'generate_header.xsl');
my $headerXsl = replaceXslKeys($headerXslSource, $license);
runXSLT($ui4Xsd, $headerXsl->filename, $uiLibHeader);

print "Running XSLT processor for uilib source...\n";
my $implXslSource = File::Spec->catfile($xmlDir, 'generate_impl.xsl');
my $implXsl = replaceXslKeys($implXslSource, $license, 'ui4_p.h');
runXSLT($ui4Xsd, $implXsl->filename, $uiLibImpl);

# uic: Header is called 'ui4.h' instead of 'ui4_p.h'

my $uicImpl = File::Spec->catfile($uicDir, 'ui4.cpp');
my $uicHeader = File::Spec->catfile($uicDir, 'ui4.h');
$license = readCppLicense($uicImpl);

print "Running XSLT processor for uic header...\n";
$headerXsl = replaceXslKeys($headerXslSource, $license);
runXSLT($ui4Xsd, $headerXsl->filename, $uicHeader);

print "Running XSLT processor for uic source...\n";
$implXsl = replaceXslKeys($implXslSource, $license, 'ui4.h');
runXSLT($ui4Xsd, $implXsl->filename, $uicImpl);

system('git', 'diff');
