#!/usr/bonsaitools/bin/perl -wT
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Gervase Markham <gerv@gerv.net>
#
# Generates mostfreq list from data collected by collectstats.pl.


use diagnostics;
use strict;
use CGI "param";
use AnyDBM_File;

use lib qw(.);

require "globals.pl";
require "CGI.pl";

ConnectToDatabase(1);
GetVersionTable();

quietly_check_login();

# Silly used-once warnings
$::userid = $::userid;
$::usergroupset = $::usergroupset;

my %dbmcount;
my %count;
my $dobefore = 0;
my $before = "";
my %before;

# Get params from URL

my $changedsince = 7;     # default one week
my $maxrows = 100;        # arbitrary limit on max number of rows
my $sortby = "dup_count"; # default to sorting by dup count

if (defined(param("sortby")))
{
  $sortby = param("sortby");
}

# Check for changedsince param, and see if it's a positive integer
if (defined(param("changedsince")) && param("changedsince") =~ /^\d{1,4}$/) 
{
  $changedsince = param("changedsince");
}

# check for max rows param, and see if it's a positive integer
if (defined(param("maxrows")) && param("maxrows") =~ /^\d{1,4}$/)
{
  $maxrows = param("maxrows");
}

# Start the page
print "Content-type: text/html\n";
print "\n";
PutHeader("Most Frequently Reported Bugs");

# Open today's record of dupes
my $today = &days_ago(0);

if (<data/duplicates/dupes$today*>)
{
  dbmopen(%dbmcount, "data/duplicates/dupes$today", 0644) || 
                            &die_politely("Can't open today's dupes file: $!");
}
else
{
  # Try yesterday's, then (in case today's hasn't been created yet)
  $today = &days_ago(1);
  if (<data/duplicates/dupes$today*>)
  {
    dbmopen(%dbmcount, "data/duplicates/dupes$today", 0644) || 
                        &die_politely("Can't open yesterday's dupes file: $!");
  }
  else
  {
    &die_politely("There are no duplicate statistics for today ($today) or yesterday.");
  }
}

# Copy hash (so we don't mess up the on-disk file when we remove entries)
%count = %dbmcount;
my $key;
my $value;
my $threshold = Param("mostfreqthreshold");

# Remove all those dupes under the threshold (for performance reasons)
while (($key, $value) = each %count)
{
  if ($value < $threshold)
  {
    delete $count{$key};
  } 
}

# Try and open the database from "changedsince" days ago
$before = &days_ago($changedsince);    

if (<data/duplicates/dupes$before*>) 
{
  dbmopen(%before, "data/duplicates/dupes$before", 0644) && ($dobefore = 1);
}

print Param("mostfreqhtml");

my %delta;

if ($dobefore) 
{
  # Calculate the deltas if we are doing a "before"
  foreach (keys(%count))
  {
    $delta{$_} = $count{$_} - $before{$_};
  }
}

# Sort, if required
my @sortedcount;

if    ($sortby eq "delta")
{
  @sortedcount = sort by_delta keys(%count);
}
elsif ($sortby eq "bug_no")
{
  @sortedcount = reverse sort by_bug_no keys(%count);
}
elsif ($sortby eq "dup_count")
{
  @sortedcount = sort by_dup_count keys(%count);
}

my $i = 0;

# Produce a string of bug numbers for a Bugzilla buglist.
my $commabugs = "";
foreach (@sortedcount) 
{
  last if ($i == $maxrows);

  $commabugs .= ($_ . ",");
  $i++;  
}

# Avoid having a comma at the end - Bad Things happen.
chop $commabugs; 

print qq|

<form method="POST" action="buglist.cgi">
<input type="hidden" name="bug_id" value="$commabugs">
<input type="hidden" name="order" value="Reuse same sort as last time">
Give this to me as a <input type="submit" value="Bug List">. (Note: the order may not be the same.)
</form>

<table BORDER>
<tr BGCOLOR="#CCCCCC">

<td><center><b>
<a href="duplicates.cgi?sortby=bug_no&maxrows=$maxrows&changedsince=$changedsince">Bug #</a>
</b></center></td>
<td><center><b>
<a href="duplicates.cgi?sortby=dup_count&maxrows=$maxrows&changedsince=$changedsince">Dupe<br>Count</a>
</b></center></td>\n|;

if ($dobefore) 
{
  print "<td><center><b>
  <a href=\"duplicates.cgi?sortby=delta&maxrows=$maxrows&changedsince=$changedsince\">Change in
  last<br>$changedsince day(s)</a></b></center></td>";
}

print "
<td><center><b>Component</b></center></td>
<td><center><b>Severity</b></center></td>
<td><center><b>Op Sys</b></center></td>
<td><center><b>Target<br>Milestone</b></center></td>
<td><center><b>Summary</b></center></td>
</tr>\n\n";

$i = 0;

foreach (@sortedcount)
{
  my $id = $_;
  SendSQL(SelectVisible("SELECT component, bug_severity, op_sys, target_milestone, short_desc, bug_status, resolution" .
                 " FROM bugs WHERE bugs.bug_id = $id", $::userid, $::usergroupset));
  next unless MoreSQLData();
  my ($component, $severity, $op_sys, $milestone, $summary, $bug_status, $resolution) = FetchSQLData();
  $summary = html_quote($summary);

  # Show all bugs except those CLOSED _OR_ VERIFIED but not INVALID or WONTFIX.
  # We want to see VERIFIED INVALID and WONTFIX because common "bugs" which aren't
  # bugs end up in this state.
  unless ( ($bug_status eq "CLOSED") || ( ($bug_status eq "VERIFIED") &&
          ! ( ($resolution eq "INVALID") || ($resolution eq "WONTFIX") ) ) ) {
    print "<tr>";
    print '<td><center>';
    if  ( ($bug_status eq "RESOLVED") || ($bug_status eq "VERIFIED") ) {
      print "<strike>";
    }
    print "<A HREF=\"show_bug.cgi?id=" . $id . "\">";
    print $id . "</A>";
    if  ( ($bug_status eq "RESOLVED") || ($bug_status eq "VERIFIED") ) {
      print "</strike>";
    }
    print "</center></td>";
    print "<td><center>$count{$id}</center></td>";
    if ($dobefore) 
    {
      print "<td><center>$delta{$id}</center></td>";
    }
    print "<td>$component</td>\n    ";
    print "<td><center>$severity</center></td>";
    print "<td><center>$op_sys</center></td>";
    print "<td><center>$milestone</center></td>";
    print "<td>$summary</td>";
    print "</tr>\n";

    $i++;
  }

  if ($i == $maxrows)
  {
    last;
  }
}

print "</table><br><br>";
PutFooter();


sub by_bug_no 
{
  return ($a <=> $b);
}

sub by_dup_count 
{
  return -($count{$a} <=> $count{$b});
}

sub by_delta 
{
  return -($delta{$a} <=> $delta{$b});
}

sub days_ago 
{
  my ($dom, $mon, $year) = (localtime(time - ($_[0]*24*60*60)))[3, 4, 5];
  return sprintf "%04d-%02d-%02d", 1900 + $year, ++$mon, $dom;
}

sub die_politely {
  my $msg = shift;

  print <<FIN;
<p>
<table border=1 cellpadding=10>
<tr>
<td align=center>
<font color=blue>$msg</font>
</td>
</tr>
</table>
<p>
FIN
    
  PutFooter();
  exit;
}