/*
   * Copyright (C) 1997, Alexander Pukhov 
   * with changes by V.Ilyin for #-models, 6 Sept 2000
   * Copyright (C) 2001-2003, CompHEP Collaboration
   *------------------------------------------------------
   * $Id: sf_pdf.c,v 1.9 2003/07/01 14:29:38 kryukov Exp $
   *
   * $Log: sf_pdf.c,v $
   * Revision 1.9  2003/07/01 14:29:38  kryukov
   * Now list of pdf's display from 1 line
   *
   * Revision 1.8  2003/07/01 13:53:09  sherstnv
   * QCD Lambda is taken from cteq** file now
   * The strfun dir contains *.tbl - original cteq
   * and *.pdf - our format of cteq.
   *
   * Revision 1.7  2003/06/25 18:46:41  kryukov
   * *** empty log message ***
   *
   * Revision 1.6  2003/04/22 09:01:19  kryukov
   * Apply indent to improve readability of files
   *
   * Revision 1.5  2003/04/19 18:32:30  kryukov
   * Change format menu function. Now it must return int value (position of selection)
   *
 */
#include <stdio.h>
#include <string.h>
#include "service2/include/os.h"
#include "service2/include/files.h"
#include "chep_crt/include/chep_crt.h"
#include "out_ext.h"

#include "num/include/tag_reader.h"
#include "num/include/tag_parser.h"
#include "num/include/subproc.h"
#include "num/include/strfun.h"
#include "num/include/pdf.h"
#include "num/include/events.h"
#include "num/include/n_comphep_.h"
#include "num/include/sf_pdf.h"

int alphaMode = 0;

static char *pdfName[2] =
{NULL, NULL};
/* static pdfStr pdfData[2];   */
static pdfStr pdfData[9];	/*  #-mdl */

static void 
comphepPdfList (char *p_name, pdfList ** list)
{
  int i;
  char *dNames[3];
  char pathfile[STRSIZ];
  char tempstr[13];

  dNames[0] = "../";
  dNames[1] = "./";
  dNames[2] = malloc ((strlen (pathtocomphep) + 13) * sizeof (char));
  strcpy (dNames[2], pathtocomphep);
  sprintf (tempstr, "strfun%c", f_slash);
  strcat (dNames[2], tempstr);

  for (i = interpret ? 1 : 0; i < 3; i++)
    {
      int len, err;
      searchrec s;
      strcpy (pathfile, dNames[i]);
      len = strlen (pathfile);
      strcat (pathfile, "*.pdf");
      err = find_first (pathfile, &s, anyfile);

      while (!err)
	{
	  pathfile[len] = 0;
	  strcat (pathfile, s.name);
	  makePdfList (pathfile, s.name, p_name, list);
	  err = find_next (&s);
	}
    }
  free (dNames[2]);
}


int 
p_pdf (char *p_name)
{
  pdfList *list = NULL;
  comphepPdfList (p_name, &list);
  if (list)
    {
      delPdfList (list);
      return 1;
    }
  else
    return 0;
}


int 
CERNpdf_number (char *pdf, char *ver, int *PDFid, int *PDFgroup)
{
  if (!strcmp (pdf, "CTEQ") ||
      !strcmp (pdf, "Cteq") ||
      !strcmp (pdf, "cteq"))
    {
      if (!strcmp (ver, "4m") || !strcmp (ver, "4M"))
	{
	  *PDFid = 34;
	  *PDFgroup = 4;
	  return 0;
	}
      if (!strcmp (ver, "4l") || !strcmp (ver, "4L"))
	{
	  *PDFid = 32;
	  *PDFgroup = 4;
	  return 0;
	}
      if (!strcmp (ver, "5m1") || !strcmp (ver, "5M1"))
	{
	  *PDFid = 53;
	  *PDFgroup = 4;
	  return 0;
	}
      if (!strcmp (ver, "5m") || !strcmp (ver, "5M"))
	{
	  *PDFid = 48;
	  *PDFgroup = 4;
	  return 0;
	}
      if (!strcmp (ver, "5l") || !strcmp (ver, "5L"))
	{
	  *PDFid = 46;
	  *PDFgroup = 4;
	  return 0;
	}
      if (!strcmp (ver, "6d") || !strcmp (ver, "6D"))
	{
	  *PDFid = 56;
	  *PDFgroup = 4;
	  return 0;
	}
      if (!strcmp (ver, "6l") || !strcmp (ver, "6L"))
	{
	  *PDFid = 55;
	  *PDFgroup = 4;
	  return 0;
	}
      if (!strcmp (ver, "6m") || !strcmp (ver, "6M"))
	{
	  *PDFid = 57;
	  *PDFgroup = 4;
	  return 0;
	}
      if (!strcmp (ver, "6l1") || !strcmp (ver, "6L1"))
	{
	  *PDFid = 58;
	  *PDFgroup = 4;
	  return 0;
	}
    }
  return 1;
}

void 
info_pdf (int i, Str_fun_Info * info)
{
  int j = 0, ii, k;
  int turn_on = 1;
  char *ver;
  char *prt;
  char *temp;
  int PDFid;
  int PDFgr;
  int unknown_pdf;

  strcpy (info->pdf_name, "CTEQ");
  info->prt_mass = 0.938;
  temp = pdfName[i];
  k = strlen (temp);
  ver = calloc (k, sizeof (char));
  prt = calloc (k, sizeof (char));
  for (ii = 8; ii < k - 1; ii++)
    {
      if (turn_on)
	{
	  j++;
	  if (temp[ii] == '(')
	    turn_on = 0;
	  else
	    ver[ii - 8] = temp[ii];
	}
      else
	prt[ii - j - 8] = temp[ii];
    }
  strcpy (info->prt_name, prt);
  free (prt);
  strcpy (info->version, ver);
  free (ver);

  unknown_pdf = CERNpdf_number (info->pdf_name, info->version, &PDFid, &PDFgr);
  if (unknown_pdf)
    {
      fprintf (stderr, "*** Uknown PDF %s or its version %s", info->pdf_name, info->version);
      exit (1);
    }
  info->N_extra_commands = 3;
  snprintf (info->extra_commands[0], 7 + intlen (PDFid), "PDFid=%i", PDFid);
  snprintf (info->extra_commands[1], 7 + intlen (PDFgr), "PDFgr=%i", PDFgr);
  snprintf (info->extra_commands[2], 11 + strlen (pdfData[i].filename), "PDFfile=\'%s\'", pdfData[i].filename);
}

void 
n_pdf (int i, char *name)
{
  i--;
  if (pdfName[i])
    strcpy (name, pdfName[i]);
  else
    strcpy (name, "PDF:");
}


int 
r_pdf (int i, char *name)
{
  i--;
  if (name == strstr (name, "PDF"))
    {
      if (pdfName[i])
	free (pdfName[i]);
      pdfName[i] = malloc (strlen (name) + 1);
      strcpy (pdfName[i], name);
      return 1;
    }
  else
    return 0;
}


int 
be_pdf (int i, double *be, double *mass)
{
  char p_name[20];
  pdfList *list = NULL;
  pdfList *list_;
  int ret_code = 0;
  static int first[2] =
  {1, 1};
  int ip, xip;			/* #-mdl */
  char *xpar;			/* #-mdl */
  xpar = "anti-proton";		/* #-mdl */

  i--;
  if (!first[i])
    freePdfData (pdfData + i);

  pinf_ (proces_1.nsub, i + 1, p_name, NULL);

  comphepPdfList (p_name, &list);
  list_ = list;
  while (list_ && ret_code == 0)
    {
      if (strcmp (list_->name, pdfName[i] + 4) == 0)
	{
	  if (i == 0 || !pdfName[0])
	    for (ip = 2; ip < 9; ip++)
	      {
		xip = ip;
		if (strstr (pdfName[i] + 4, xpar))
		  {
		    if (ip == 8)
		      xip = 4;
		    if (ip == 4)
		      xip = 8;
		    if (ip == 7)
		      xip = 5;
		    if (ip == 5)
		      xip = 7;
		  }
		getPdfData (list_->pathfile, list_->file, xip, pdfData + ip);	/* #-mdl */
	      }
	  ret_code = !getPdfData (list_->pathfile, list_->file, list_->position, pdfData + i);
	}
      list_ = list_->next;
    }
  if (list)
    delPdfList (list);
  if (ret_code)
    {
      first[i] = 0;
      if (pdfData[i].alpha)
	alphaMode = i + 1;
      if (pdfData[i].pow1 < 0)
	*be = pdfData[i].pow1 + 1;
      else
	*be = 1.;
      *mass = pdfData[i].mass;
    }
  return ret_code;
}

#define WIDTH 30
int 
m_pdf (int i)
{
  pdfList *list = NULL;
  pdfList *list_ = NULL;
  int k = 0, k1;
  char *strmen;
  void *pscr = NULL;
  char p_name[20];

  i--;
  pinf_ (proces_1.nsub, i + 1, p_name, NULL);

  comphepPdfList (p_name, &list_);
  if (!list_)
    {
      return 0;
    }
  else
    {
      list = (pdfList *) malloc (sizeof (pdfList));
      list->next = list_;
      list->name = strdup ("OFF");
      list->pathfile = NULL;
      list->file = NULL;
      list->position = 0;
    }
  for (list_ = list; list_; list_ = list_->next)
    k++;
  strmen = malloc (2 + WIDTH * k);
  strmen[0] = WIDTH;
  strmen[1] = 0;
  for (list_ = list; list_; list_ = list_->next)
    sprintf (strmen + strlen (strmen), " PDF:%-*.*s", WIDTH - 5, WIDTH - 5, list_->name);
  k=0;
  menu1 (80 - 4 - WIDTH, 7, "", strmen, "", &pscr, &k);
  if (k)
    {
      k1 = k;
      k1--;
      for (list_ = list; k1; k1--)
	list_ = list_->next;
      if (pdfName[i])
	free (pdfName[i]);
      pdfName[i] = malloc (5 + strlen (list_->name));
      sprintf (pdfName[i], "PDF:%s", list_->name);
    }

  free (strmen);
  put_text (&pscr);
  delPdfList (list);
  return k;
}

double 
c_pdf (int i, double x, double q)
{
  double r;

  i--;
  r = interFunc (x, q, pdfData + i);
  if (!r)
    return 0.;
  if (pdfData[i].pow0)
    r *= pow (x, pdfData[i].pow0);
  if (pdfData[i].pow1 > 0)
    r *= pow (1 - x, pdfData[i].pow1);

  if (r < 0)
    r = 0;
  return r;
}

double 
alpha_pdf (double q)
{
  return interAlpha (q, pdfData + alphaMode - 1);
}

int 
pdfnamecmp (void)
{
  if (!strcmp (pdfName[0], pdfName[1]))
    return 1;
  return 0;
}
