/*****************************************************************************
 *                                  _   _ ____  _     
 *  Project                     ___| | | |  _ \| |    
 *                             / __| | | | |_) | |    
 *                            | (__| |_| |  _ <| |___ 
 *                             \___|\___/|_| \_\_____|
 *
 *  The contents of this file are subject to the Mozilla Public License
 *  Version 1.0 (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 Curl.
 *
 *  The Initial Developer of the Original Code is Daniel Stenberg.
 *
 *  Portions created by the Initial Developer are Copyright (C) 1998.
 *  All Rights Reserved.
 *
 * ------------------------------------------------------------
 * Main author:
 * - Daniel Stenberg <Daniel.Stenberg@sth.frontec.se>
 *
 * 	http://www.fts.frontec.se/~dast/curl/
 *
 * $Source: /cvs/curl/curl/lib/progress.c,v $
 * $Revision: 1.4 $
 * $Date: 1999/04/12 23:11:10 $
 * $Author: dast $
 * $State: Exp $
 * $Locker:  $
 *
 * ------------------------------------------------------------
 ****************************************************************************/

#include "../include/setup.h"

#ifdef WIN32
#include <time.h>
#endif

#include "../include/curl.h"
#include "urldata.h"

#include "progress.h"

/* --- start of progress routines --- */
int progressmax=-1;

void ProgressInit(struct UrlData *data, int max)
{
  static char beenhere=0;

  if(beenhere || (data->conf&(CONF_NOPROGRESS|CONF_MUTE)))
    return;
  beenhere=1;
  progressmax = max;
  if(-1 == max)
    return;
  if(progressmax <= LEAST_SIZE_PROGRESS) {
    progressmax = -1; /* disable */
    return;
  }

  fprintf(stderr, "  %%   Received   Total  Speed   Time left  Total   Curr.Speed\n");
}

void time2str(char *r, int t)
{
  int h = (t/3600);
  int m = (t-(h*3600))/60;
  int s = (t-(h*3600)-(m*60));
  sprintf(r,"%3d:%02d:%02d",h,m,s);
}

void ProgressShow(struct UrlData *data,
                  int point, struct timeval start, struct timeval now, bool force)
{
  static long lastshow;
  double percen;

  double spent;
  double speed;

#define CURR_TIME 5

  static int speeder[ CURR_TIME ];
  static int speeder_c=0;

  int nowindex = speeder_c% CURR_TIME;
  int checkindex;
  int count;

  if(!force && (point != progressmax) && (lastshow == tvlong(now)))
    return; /* never update this more than once a second if the end isn't 
               reached */

  spent = tvdiff (now, start);
  speed = point/(spent!=0.0?spent:1.0);
  if(!speed)
    speed=1;

  /* point is where we are right now */
  speeder[ nowindex ] = point;
  speeder_c++; /* increase */
  count = ((speeder_c>=CURR_TIME)?CURR_TIME:speeder_c) - 1;
  checkindex = (speeder_c>=CURR_TIME)?speeder_c%CURR_TIME:0;

  /* find out the average speed the last CURR_TIME seconds */
  data->current_speed = (speeder[nowindex]-speeder[checkindex])/(count?count:1);

#if 0
  printf("NOW %d(%d) THEN %d(%d) DIFF %lf COUNT %d\n",
	 speeder[nowindex], nowindex,
	 speeder[checkindex], checkindex,
	 data->current_speed, count);
#endif

  if(data->conf&(CONF_NOPROGRESS|CONF_MUTE))
    return;

  if(-1 != progressmax) {
    char left[20],estim[20];
    int estimate = progressmax/(int) speed;
    
    time2str(left,estimate-(int) spent); 
    time2str(estim,estimate);

    percen=(double)point/progressmax;
    percen=percen*100;

    fprintf(stderr, "\r%3d %8d  %8d %6.0lf %s %s %6.0lf   ",
            (int)percen, point, progressmax,
            speed, left, estim, data->current_speed);
  }
  else
    fprintf(stderr, "\r%d bytes received in %.3lf seconds (%.0lf bytes/sec)",
            point, spent, speed);

  lastshow = now.tv_sec;
}

void ProgressEnd(struct UrlData *data)
{
  if(data->conf&(CONF_NOPROGRESS|CONF_MUTE))
    return;
  fputs("\n", stderr);
}

/* --- end of progress routines --- */
