DROP FUNCTION PATS.ABBR_ISSUE_TEXT;

CREATE OR REPLACE FUNCTION PATS."ABBR_ISSUE_TEXT"  (p_itxt VARCHAR2)
RETURN VARCHAR2
AS
 v_abbr_itxt VARCHAR2(80);
BEGIN
  IF LENGTH(p_itxt) < 81 THEN
    v_abbr_itxt := p_itxt;
  ELSE
    v_abbr_itxt := SUBSTR(p_itxt,1,77)||'...';
  END IF;
  RETURN v_abbr_itxt;
 END abbr_issue_text;
 
/
DROP FUNCTION PATS.CALCULATE_ROC_DATE_OVERDUE;

CREATE OR REPLACE FUNCTION PATS."CALCULATE_ROC_DATE_OVERDUE"  (p_date_of_contact DATE)
RETURN DATE
AS
  -- Return the date_overdue for a ROC
  v_date_overdue DATE;
  v_days INT;
BEGIN
   -- Find official number of days before ROC becomes overdue in the National Parameters
   SELECT days_to_process_roc INTO v_days
     FROM national_pats_parameters
	 WHERE id=1;
   -- Then calculate date overdue for ROC based on date of contact.
   IF v_days > 0 THEN
     v_date_overdue := p_date_of_contact + v_days;
   ELSE
     v_date_overdue := p_date_of_contact + 7;
   END IF;
   RETURN v_date_overdue;
 END calculate_roc_date_overdue;
 
/
DROP FUNCTION PATS.CALENDAR_TO_FISCAL_YEAR;

CREATE OR REPLACE FUNCTION PATS."CALENDAR_TO_FISCAL_YEAR"  (p_date DATE)
RETURN INT
AS

 v_int INT;
BEGIN
  v_int := EXTRACT(MONTH FROM p_date);
	IF v_int < 10
	  THEN v_int := EXTRACT(YEAR FROM p_date);
	ELSE
	  v_int := EXTRACT(YEAR FROM p_date) + 1;
	END IF;
	RETURN v_int;
 END calendar_to_fiscal_year;
 
/
DROP FUNCTION PATS.DISPLAYABLE_NAME;

CREATE OR REPLACE FUNCTION PATS."DISPLAYABLE_NAME"  (
	p_lastname IN VARCHAR2
	, p_firstname IN VARCHAR2
	, p_middlename IN VARCHAR2
	, p_suffix IN VARCHAR2
	, p_degree IN VARCHAR2
	, p_prefix IN VARCHAR2
	, p_outputlength IN INT
	, p_format IN INT)
 RETURN VARCHAR2
 IS

/* Takes name components and returns a displayable form of the name.
   If p_format=1, the name is returned with the first name first:
   "prefix first middle last suffix degree" ex., "Mr. John Q. Public Sr. Phd".
   If p_format=2, the name is returned without the prefix, and with the last name first:
   "last, first middle suffix degree" ex., "Public, John Q. Sr. Phd".
   Length is controlled by the parameter p_outputlength, with a default of 120 characters.

   If the name is too long, we first drop the degree (if any)
   If still too long, we drop the prefix (if any)
   If still too long, we truncate the middle name up to the initial character.
   If still too long, we drop the suffix.
   If still too long, we truncate the first name up to the initial character
   If still too long, we truncate the last name up to the initial character
   Finally, if still too long, we truncate the name from the right.  */

 -- Define variables
 v_lastname VARCHAR2(35);
 v_firstname VARCHAR2(25);
 v_middlename VARCHAR2(25);
 v_degree VARCHAR2(10);
 v_prefix VARCHAR2(10);
 v_suffix VARCHAR2(10);
 v_outputlength INT;
 v_format INT;
 v_llen INT;
 v_flen INT;
 v_mlen INT;
 v_slen INT;
 v_namelen INT;
 v_plen INT;
 v_dlen INT;
 v_newname VARCHAR2(120);

BEGIN

/* The default format is #1 (first name first) */
	v_format := 1;
	IF (p_format IS NOT NULL) AND (p_format = 2) THEN v_format := 2;
	END IF;

/* Store the lengths of the name parts in local variables*/
	v_prefix := RTRIM(p_prefix);
	IF v_format = 2 THEN v_prefix := '';
	END IF;

	v_lastname := RTRIM(p_lastname);
	v_firstname := RTRIM(p_firstname);
	v_middlename := RTRIM(p_middlename);
	v_suffix := RTRIM(p_suffix);
	v_degree := RTRIM(p_degree);
	v_llen  := LENGTH(v_lastname);
	v_flen  := LENGTH(v_firstname);
	v_mlen  :=  0;
	IF v_middlename IS NOT NULL THEN v_mlen := LENGTH(v_middlename);
	END IF;

	v_slen := 0;
	IF v_suffix IS NOT NULL THEN v_slen := LENGTH(v_suffix);
	END IF;

	v_dlen := 0;
	IF v_degree IS NOT NULL THEN v_dlen := LENGTH(v_degree);
	END IF;

	v_plen := 0;
	IF v_prefix IS NOT NULL THEN v_plen := LENGTH(v_prefix);
	END IF;

/* Set the default length for the output to 120. The length of the output name will be equal to the
   combined length of the name parts, plus 1 for the space we'll insert between each name part. */
	v_newname := '';
	IF p_outputlength IS NULL THEN v_outputlength := 120;
	END IF;
	v_namelen := v_llen+v_flen+v_mlen+v_slen+v_plen+v_dlen+1;
	IF v_mlen>0 THEN v_namelen := v_namelen+1;
	END IF;
	IF v_slen>0 THEN v_namelen := v_namelen+1;
	END IF;
	IF v_plen>0 THEN v_namelen := v_namelen+1;
	END IF;
	IF v_dlen>0 THEN v_namelen := v_namelen+1;
	END IF;
	IF v_format = 2 THEN v_namelen := v_namelen+1;
	END IF;

/* If output name is too long, drop the degree. */
	IF (v_dlen > 0) AND (v_namelen > p_outputlength) THEN
		v_namelen := v_namelen-v_dlen-1;
		v_dlen := 0;
	END IF;

/* If output name is too long, drop the prefix. */
	IF (v_plen > 0) AND (v_namelen > p_outputlength) THEN
		v_namelen := v_namelen - v_plen - 1;
		v_plen := 0;
	END IF;

/* If the name is still too long, truncate the middle name from the right hand side, until it
   either is no longer too long, or there is just the first initial left.*/
	IF (v_mlen > 0) AND (v_namelen > p_outputlength) THEN
		v_namelen  :=  v_namelen - v_mlen;
		IF (v_namelen+1) <= p_outputlength
		  THEN v_middlename := SUBSTR(v_middlename,1,p_outputlength-v_namelen);
		ELSE v_middlename := SUBSTR(v_middlename,1,1);
		END IF;
		v_namelen := v_namelen +  LENGTH(v_middlename);
	END IF;

/* If the output name will still be too long, eliminate the name suffix (if there is one). */
	IF (v_slen > 0) AND (v_namelen > p_outputlength) THEN
		v_namelen := v_namelen - v_slen - 1;
		v_slen := 0;
	END IF;

/* If the name is still too long, truncate the first name from the right hand side, until it
   either is no longer too long, or there is just the first initial left.*/
	IF (v_flen > 0) AND (v_namelen > p_outputlength) THEN
		v_namelen := v_namelen - v_flen;
		IF (v_namelen+1) <= p_outputlength
		  THEN v_firstname := SUBSTR(v_firstname,1,p_outputlength-v_namelen);
		ELSE v_firstname := SUBSTR(v_firstname,1,1);
		END IF;
		v_namelen := v_namelen +  LENGTH(v_firstname);
	END IF;

/* If the name is still too long, truncate the last name from the right hand side, until it
   either is no longer too long, or there is just the first initial left.*/
	IF (v_flen > 0) AND (v_namelen > p_outputlength) THEN
		v_namelen := v_namelen - v_llen;
		IF (v_namelen+1) <= p_outputlength
		    THEN v_lastname := SUBSTR(v_lastname,1,(p_outputlength-v_namelen));
		ELSE v_lastname := SUBSTR(v_lastname,1,1);
		END IF;
		v_namelen := v_namelen +  LENGTH(v_lastname);
	END IF;

/* Format #1: output name with prefix first name middle name last name suffix degree.*/
	IF (v_format = 1) AND (v_lastname IS NOT NULL) THEN
		v_newname := v_lastname;
		IF v_slen>0 THEN v_newname := v_newname||' '||v_suffix;
		END IF;
		IF v_dlen>0 THEN v_newname := v_newname||' '||v_degree;
		END IF;
		IF v_mlen>0 THEN v_newname := v_middlename||' '||v_newname;
		END IF;
		IF v_flen>0 THEN v_newname := v_firstname||' '||v_newname;
		END IF;
		IF v_plen>0 THEN v_newname := v_prefix||' '||v_newname;
		END IF;
	END IF;

/* Format #2: output name with last name first, followed by first, middle, suffix, degree (no prefix) */
	IF (v_format = 2) AND (v_lastname IS NOT NULL) THEN
		v_newname := v_lastname||', '||v_firstname;
		IF v_mlen>0 THEN v_newname := v_newname||' '||v_middlename;
		END IF;
		IF v_slen>0 THEN v_newname := v_newname||' '||v_suffix;
		END IF;
		IF v_dlen>0 THEN v_newname := v_newname||' '||v_degree;
		END IF;
	END IF;

/* Finally, if the output name is still too long, truncate from the right.*/
	IF  LENGTH(v_newname) > p_outputlength THEN v_newname := SUBSTR(v_newname,1,p_outputlength);
	END IF;

	RETURN v_newname;
END DISPLAYABLE_NAME;
 
/


GRANT EXECUTE ON PATS.DISPLAYABLE_NAME TO PATSRPTS;
DROP FUNCTION PATS.DISPLAYABLE_TIME_ZONE;

CREATE OR REPLACE FUNCTION PATS."DISPLAYABLE_TIME_ZONE"  (p_date TIMESTAMP WITH TIME ZONE)
RETURN VARCHAR2
AS
 v_tzr VARCHAR2(6);
 v_timezone VARCHAR2(3);
BEGIN
  v_tzr := TO_CHAR(p_date,'TZR');
  CASE v_tzr
    WHEN '-04:00' THEN v_timezone := 'EDT';
	WHEN '-05:00' THEN v_timezone := 'EST';
	WHEN '-06:00' THEN v_timezone := 'MDT';
	WHEN '-07:00' THEN v_timezone := 'PDT';
	ELSE v_timezone := 'UNK';
  END CASE;
RETURN v_timezone;
END displayable_time_zone;
 
/
DROP FUNCTION PATS.NEW_ROC_NUMBER;

CREATE OR REPLACE FUNCTION PATS."NEW_ROC_NUMBER"  (p_station_number VARCHAR2    -- Station Number from Pats_Institution table
 , p_date_of_contact DATE)    -- DateTime when contact occurred
RETURN VARCHAR2
AS

/* Return a new ROC Number for a given Station Number and Date of Contact.
 We determine the Fiscal Year based on the calendar Date of Contact.*/
 v_old_contact_no VARCHAR2(16);
 v_new_contact_FY CHAR(4);
 v_contact_counter VARCHAR2(5);
 v_counter INT;
 v_new_ROC_number VARCHAR2(16);
BEGIN

  -- Get Fiscal Year of new contact
  v_new_contact_FY := TO_CHAR(pats.calendar_to_fiscal_year(p_date_of_contact));
  v_new_ROC_number := NULL;

  -- Find the last ROC added for this station and year.
  SELECT MAX(roc_number) INTO v_old_contact_no FROM pats.report_of_contact
    WHERE roc_number LIKE (p_station_number || '.' || v_new_contact_FY || '%');

  -- If this is the first ROC for this station/FY combination, build ROCNumber with counter=00001
   IF v_old_contact_no IS NULL THEN
        v_new_ROC_number := p_station_number || '.' || v_new_contact_FY || '00001';
   /* Else, if year hasn't changed, increment counter and build new contactNumber. Pad
   counter part of contact number with zeros.*/
   ELSE
     v_contact_counter := SUBSTR(v_old_contact_no, (INSTR(v_old_contact_no, '.')+5), 5);
     v_counter := TO_NUMBER(v_contact_counter) + 1;
     v_contact_counter := TO_CHAR(v_counter);
     v_contact_counter := SUBSTR('00000',1,5-(LENGTH(v_contact_counter))) || v_contact_counter;
     v_new_ROC_number := p_station_number || '.' || v_new_contact_FY || v_contact_counter;
   END IF;

 RETURN v_new_ROC_number;

END new_ROC_number;
 
/
DROP FUNCTION PATS.RETURN_ID_TABLE;

CREATE OR REPLACE FUNCTION PATS."RETURN_ID_TABLE"  (p_id_list IN VARCHAR2)
   RETURN pats.id_list
 AS
   v_id_list_out pats.id_list := pats.id_list(NULL);
   v_id INT;
   v_id_list VARCHAR2(300);
   v_end INT;
   v_index INT := 0;
 BEGIN
   v_id_list := p_id_list||',';
   /* Extract the institution ids from comma-delimited input string, and
      load into the station_number_table */
   LOOP
      v_end := INSTR(v_id_list,',');
	  v_id := SUBSTR(v_id_list,1,v_end-1);
	  v_id_list := SUBSTR(v_id_list,v_end+1,200);
      IF v_id IS NOT NULL THEN
	    v_index := v_index + 1;
	    IF v_index > 1 THEN
	      v_id_list_out.EXTEND(1);
	    END IF;
	    v_id_list_out(v_index) := v_id;
	  ELSE
	    EXIT;
      END IF;
   END LOOP;
   RETURN v_id_list_out;
 END return_id_table;
 
/
DROP FUNCTION PATS.STANDARD_NAME;

CREATE OR REPLACE FUNCTION PATS."STANDARD_NAME"  (p_namepart IN VARCHAR2, p_outlength IN INT, p_leaveblanks IN CHAR)
    RETURN VARCHAR2
 IS
  -- Define variables
  v_namein VARCHAR2(35);
  v_nameout VARCHAR2(35);
  v_namelen INT;
  v_asciival INT;
  v_outlength INT := 35;
 BEGIN
  -- initialize variables, convert input name to upper case.
  IF p_outlength IS NOT NULL THEN v_outlength := p_outlength;
  END IF;
  v_namein := UPPER(p_namepart);
  v_namelen := LENGTH(p_namepart);
  v_nameout := '';

  /* Build the output name by examining one character at a time. All spaces and punctuation
     are removed from the output name unless p_leaveblanks=1 (in which case spaces are left).*/
  WHILE v_namelen > 0 LOOP
    v_asciival := ASCII(v_namein);
    IF
      ((v_asciival>64) AND (v_asciival<91)) THEN v_nameout := v_nameout || SUBSTR(v_namein,1,1);
    ELSIF
      ((v_asciival>47) AND (v_asciival<58)) THEN v_nameout := v_nameout || SUBSTR(v_namein,1,1);
    ELSIF
      ((v_asciival=32) AND (p_leaveblanks IS NOT NULL) AND (p_leaveblanks=1))
           THEN v_nameout := v_nameout || SUBSTR(v_namein,1,1);
    END IF;
    IF v_namelen>1 THEN v_namein := SUBSTR(v_namein,2,v_namelen);
    END IF;
    v_namelen := v_namelen-1;
  END LOOP;

  -- Return formatted name
  RETURN SUBSTR(v_nameout,1,v_outlength);
 END standard_name;
 
/


GRANT EXECUTE ON PATS.STANDARD_NAME TO PATSHOST_ROLE;

GRANT EXECUTE ON PATS.STANDARD_NAME TO PATSRPTS;
