#!/usr/bin/perl -w
#
# Copyright (c) 2022 Adrian Schroeter, SUSE LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
#
# OBS Git LFS provider
# 
# This service answers git LFS requests and let OBS deliver the files
# based on a static database.
#
# This is only supposed to be used for converted sources from classic
# OBS source repositories. This is not supposed to be used for sources
# which are supposed to be actively maintained in git directly.
#

BEGIN {
  my ($wd) = $0 =~ m-(.*)/- ;
  $wd ||= '.';
  unshift @INC,  "$wd";
}

use Data::Dumper;
use JSON::XS ();

use BSServer;
use BSRPC ':https';
use BSDispatch;
use BSXML;

use strict;

my $port = 9998;
my $proto = 'http';

my $obsurl = "https://api.opensuse.org/public";
my $header = "X-SCM-BRIDGE-COOKIE: not_configured";
eval {
  use config;
  $header = "X-SCM-BRIDGE-COOKIE: $config::shared_cookie" if $config::shared_cookie;
  $obsurl = $config::obsurl;
};

sub repositoryresults {
  my ($cgi) = @_;

  my $scmrepo = $cgi->{'scmrepository'};
  my $scmbranch = $cgi->{'scmbranch'};

  my $query = {'scmrepository' => $scmrepo,
	       'scmbranch'     => $scmbranch };
  my @args = BSRPC::args($query, 'scmrepository', 'scmbranch');
  my $r = BSRPC::rpc({'uri' => "$obsurl/build/_result",
	              'request' => 'GET',
	              'headers' => [$header]},
                      $BSXML::resultlist,
                     @args);

  my $html = '<table> <tr> <th>Project</th><th>Package</th> <th>Repository</th> <th>Architecture</th> <th>Result</th> </tr>';
  my $lastproject = '';
  my $lastpackage = '';
  my $lastrepo = '';
  my $count = 0;
  for my $result (@{$r->{'result'} || []}) {
    my $project = $result->{'project'};
    my $package = $result->{'status'}[0]->{'package'} || undef;
    my $repo    = $result->{'repository'};
    my $arch    = $result->{'arch'};
    my $code    = $result->{'status'}[0]->{'code'} || 'unknown';

    $project = '' if $project eq $lastproject;
    $package = '' if $package eq $lastpackage;
    $repo = ''    if $repo eq $lastrepo;
    $count = $count + 1;

    my $bgcolor = "#fff";
    $bgcolor = "#bbb" if $code eq 'scheduled' || $code eq 'building' ||  $code eq 'finished' || $code eq 'blocked';
    my $color = "#FFF";
    $color = "#6EB927" if $code eq 'succeeded';
    $color = "#666" if $code eq 'signing';
    $color = "#222" if $code eq 'finished';
    $color = "#c00" if $code eq 'unresolvable';
    $color = "#e00" if $code eq 'broken';
    $color = "#f00" if $code eq 'failed';
    $color = "#fff" if $code eq 'blocked';

    $html .= "<tr><td>$project</td><td>$package</td> <td>$repo</td> <td>$arch</td> <td bgcolor=\"$bgcolor\"><font color=\"$color\">$code</font></td> </tr>\n";

    $lastproject = $project unless $project eq '' ;
    $lastpackage = $package unless $package eq '' ;
    $lastrepo    = $repo    unless $repo eq '';
    last if $count > 10;
  };
  $html .= '</table>';
  $html .= '<p>.... uncollapsing not implemeted...</p>' if $count > 10;
  return $html;
}

sub repositoryevent {
  die("need event data as content\n") unless BSServer::have_content();
  my $batch_json = BSServer::read_data(10000000);
  my $batch = JSON::XS::decode_json($batch_json);

  die("no ref given\n") unless $batch->{'ref'};
  die("no repository given\n") unless $batch->{'repository'};
  die("no clone repository given\n") unless $batch->{'repository'}->{'clone_url'};

  my $branch = $batch->{'ref'};
  # a bit of guessing here...
  $branch =~ s/refs\/heads\///;
  $branch =~ s/refs\/tags\///;
  $branch =~ s/refs\///;
  print "Forward url $batch->{'repository'}->{'clone_url'} for branch $branch\n";

  my $cgi = { 'cmd'           => 'triggerscmsync',
	      'scmrepository' => $batch->{'repository'}->{'clone_url'},
	      'scmbranch'     => $branch };
  $cgi->{'isdefaultbranch'} = 1 if $batch->{'repository'}->{'default_branch'} eq $branch;
  my @args = BSRPC::args($cgi, 'cmd', 'scmrepository', 'scmbranch', 'isdefaultbranch');
  my $h = BSRPC::rpc({'uri' => "$obsurl/source",
	              'request' => 'POST',
	              'headers' => [$header]}, undef, @args);

  my $resp = {
    answer => 'thank you',
  };
  #  print Dumper(JSON::XS::encode_json($resp));
  return (JSON::XS::encode_json($resp), 'Content-Type: application/json');
}

sub hello {
  return ("{\"message\": \"OBS Gitea Bridge\"}\n", 'Content-Type: application/json');
}

sub errorreply {
  my ($err, $code, $tag, @hdrs) = @_;
  $err = JSON::XS::encode_json({'message' => $tag});
  BSServer::reply("$err\n", "Status: $code $tag", 'Content-Type: application/json', @hdrs);
}

sub dispatch {
  my ($conf, $req) = @_;
  return BSDispatch::dispatch($conf, $req);
}

# define server
my $dispatches = [
  '/' => \&hello,
  'GET:/repositoryresults scmrepository:? scmbranch:? code:? lastbuild:? multibuild:? locallink:?' => \&repositoryresults,
  'POST:/repositoryevent' => \&repositoryevent,
];

my $conf = {
  'port' => $port,
  'proto' => $proto,
  'dispatch' => \&dispatch,
  'dispatches' => $dispatches,
  'errorreply' => \&errorreply,
  'setkeepalive' => 1,
  'maxchild' => 20,
};

BSDispatch::compile($conf);
BSServer::serveropen($conf->{'port'});
BSServer::server($conf);
