create or replace PACKAGE BODY PACK_SEN IS

    -- PROCEDURES
    PROCEDURE valori_iniziali_utenti
    IS
    BEGIN
        INSERT INTO UTENTI VALUES(3331231231, 'Leonardo', 'Catello',
                                    'NA', 'San Giorgio a Cremano', 80046,
                                    'Via Roma', 23);
        INSERT INTO UTENTI VALUES(3334564564, 'Daiana', 'Cipollaro',
                                    'MI', 'Milano', 20019,
                                    'Via Torino', 1);
        INSERT INTO UTENTI VALUES(3662342342, 'Francesco', 'Di Serio',
                                    'CN', 'Cuneo', 12100,
                                    'Via Milano', 40);
        INSERT INTO UTENTI VALUES(3667897897, 'Ciro', 'Gallucci',
                                    'RM', 'Tivoli', 00019,
                                    'Via Napoli', 7);
    END;

-----------------------------------

    PROCEDURE insert_utente(
        InNumeroDiTelefono IN NUMBER,
        InNome IN VARCHAR2,
        InCognome IN VARCHAR2,
        InProvincia IN CHAR,
        InCittà IN VARCHAR2,
        InCAP IN NUMBER,
        InVia IN VARCHAR2,
        InNumeroCivico IN NUMBER
    )
    IS
    BEGIN
        INSERT INTO UTENTI VALUES(InNumeroDiTelefono, InNome, InCognome,
                                InProvincia, InCittà, InCAP,
                                InVia, InNumeroCivico);
    END;

-----------------------------------

    PROCEDURE stampa_utenti
    IS
        CURSOR cursore IS SELECT * FROM UTENTI;
        record cursore%ROWTYPE;
        counter number := 0;
    BEGIN
        OPEN cursore;
        DBMS_OUTPUT.PUT_LINE('Tabella UTENTI');
        LOOP
            counter := counter + 1;
            FETCH cursore INTO record;  -- Prelevato record corrente richiesto
            EXIT WHEN cursore%NOTFOUND; -- Restituisce TRUE quando la FETCH più recente non ha restituito righe
            DBMS_OUTPUT.PUT_LINE('Riga n# '     || counter);
            DBMS_OUTPUT.PUT_LINE('  Numero di telefono: '  || record.NumeroDiTelefono);
            DBMS_OUTPUT.PUT_LINE('  Nome: '                || record.Nome);
            DBMS_OUTPUT.PUT_LINE('  Cognome: '             || record.Cognome);
            DBMS_OUTPUT.PUT_LINE('  Provincia: '           || record.Provincia);
            DBMS_OUTPUT.PUT_LINE('  Città: '               || record.Città);
            DBMS_OUTPUT.PUT_LINE('  CAP: '                 || record.CAP);
            DBMS_OUTPUT.PUT_LINE('  Via: '                 || record.Via);
            DBMS_OUTPUT.PUT_LINE('  Numero civico: '       || record.NumeroCivico);
            DBMS_OUTPUT.PUT_LINE('');
        END LOOP;
        CLOSE cursore;
    END;

-----------------------------------

    PROCEDURE delete_utente(
        InNumeroDiTelefono IN NUMBER
    )
    IS
        -- variabile per la verifica dell'esistenza dell'utente
        utente_presente NUMBER := 0;
        -- dichiarazione dell'eccezione
        UTENTE_NON_ESISTENTE EXCEPTION;
    BEGIN
    -- Conteggia il numero di utenti presenti nella tabella utenti a cui numero corrisponde il numero in ingresso
    --   se non trova il numero -> utente_ presente non aumenta di valore e chiama Exceprion
        SELECT COUNT(*) INTO utente_presente FROM UTENTI U
                        WHERE U.NumeroDiTelefono = InNumeroDiTelefono;
        IF (utente_presente = 0)
        THEN
            RAISE UTENTE_NON_ESISTENTE;
        END IF;
        -- utente trovato correttamente
        DELETE FROM UTENTI WHERE (NumeroDiTelefono = InNumeroDiTelefono);
    EXCEPTION
        WHEN UTENTE_NON_ESISTENTE
        THEN
            DBMS_OUTPUT.PUT_LINE('Cancellamento rifiutato: utente non esistente.');
            RAISE_APPLICATION_ERROR(-20600,'Errore cancellamento di un utente non esistente.');
    END;

-----------------------------------

    PROCEDURE valori_iniziali_dipartimenti
    IS
    BEGIN
        INSERT INTO DIPARTIMENTI VALUES(idDip_seq.NEXTVAL, 115, 'Vigili del Fuoco',
                                    0, 50,
                                    'NA', 'Napoli', 80100,
                                    'Largo Tarantini', 1);
        INSERT INTO DIPARTIMENTI VALUES(idDip_seq.NEXTVAL, 118, 'Pronto Soccorso',
                                    0, 70,
                                    'TO', 'Torino', 10126,
                                    'Corso Bramante', 88);
        INSERT INTO DIPARTIMENTI VALUES(idDip_seq.NEXTVAL, 113, 'Polizia di Stato',
                                    0, 50,
                                    'MI', 'Milano', 20121,
                                    'Via Fatebenefratelli', 11);
        INSERT INTO DIPARTIMENTI VALUES(idDip_seq.NEXTVAL, 112, 'Arma dei Carabinieri',
                                    0, 40,
                                    'BA', 'Bari', 70121,
                                    'Largo Tarantini', '1');
        INSERT INTO DIPARTIMENTI VALUES(idDip_seq.NEXTVAL, 117, 'Guardia di Finanza',
                                    0, 40,
                                    'RM', 'Roma', 00162,
                                    'Viale XXI Aprile', 51);
        INSERT INTO DIPARTIMENTI VALUES(idDip_seq.NEXTVAL, 112, 'Esercito',
                                    0, 30,
                                    'PA', 'Palermo', 90134,
                                    'Piazza del Parlamento', 5);
    END;

-----------------------------------

    PROCEDURE insert_dipartimento(
        InNumeroEmergenza IN NUMBER,
        InTipologia IN VARCHAR2,
        InNumeroVeicoli IN NUMBER,
        InProvincia IN CHAR,
        InCittà IN VARCHAR2,
        InCAP IN NUMBER,
        InVia IN VARCHAR2,
        InNumeroCivico IN NUMBER
    )
    IS
    BEGIN
        INSERT INTO DIPARTIMENTI VALUES(idDip_seq.NEXTVAL, InNumeroEmergenza, InTipologia,
                                0, InNumeroVeicoli,
                                InProvincia, InCittà, InCAP,
                                InVia, InNumeroCivico);
    END;

-----------------------------------

    PROCEDURE stampa_dipartimenti
    IS
        CURSOR cursore IS SELECT * FROM DIPARTIMENTI;
        record cursore%ROWTYPE;
        counter number := 0;
    BEGIN
        OPEN cursore;
        DBMS_OUTPUT.PUT_LINE('Tabella DIPARTIMENTI');
        LOOP
            counter := counter + 1;
            FETCH cursore INTO record;
            EXIT WHEN cursore%NOTFOUND;
            DBMS_OUTPUT.PUT_LINE('Riga n# '  || counter);
            DBMS_OUTPUT.PUT_LINE('  ID: '               || record.ID);
            DBMS_OUTPUT.PUT_LINE('  Numero emergenza: '  || record.NumeroEmergenza);
            DBMS_OUTPUT.PUT_LINE('  Tipologia: '        || record.Tipologia );
            DBMS_OUTPUT.PUT_LINE('  Numero veicoli: '    || record.NumeroVeicoli);
            DBMS_OUTPUT.PUT_LINE('  Numero operatori: '  || record.NumeroOperatori);
            DBMS_OUTPUT.PUT_LINE('  Provincia: '        || record.Provincia);
            DBMS_OUTPUT.PUT_LINE('  Città: '            || record.Città);
            DBMS_OUTPUT.PUT_LINE('  CAP: '              || record.CAP);
            DBMS_OUTPUT.PUT_LINE('  Via: '              || record.Via);
            DBMS_OUTPUT.PUT_LINE('  Numero civico: '    || record.NumeroCivico );
            DBMS_OUTPUT.PUT_LINE('');
            END LOOP;
        CLOSE cursore;
    END;
----------------------------------

    PROCEDURE delete_dipartimento(
        InID IN NUMBER
    )
    IS
        -- variabile per la verifica dell'esistenza del dipartimento
        dipartimento_presente NUMBER := 0;
        -- dichiarazione dell'eccezione
        DIPARTIMENTO_NON_ESISTENTE EXCEPTION;
    BEGIN
    -- Conteggia il numero di dipartimenti presenti nella tabella dipartimento che hanno ID = InID
    --   e il valore del conteggio viene messo dento a dipartimento_presente
    --   se non trova il numero -> dipartimento_presente non aumenta di valore e chiama Exception
        SELECT COUNT(*) INTO dipartimento_presente FROM DIPARTIMENTI D
                        WHERE D.ID = InID;
        IF (dipartimento_presente = 0)
        THEN
            RAISE DIPARTIMENTO_NON_ESISTENTE;
        END IF;
        -- dipartimento trovato correttamente
        DELETE FROM DIPARTIMENTI WHERE (ID = InID);
    EXCEPTION
        WHEN DIPARTIMENTO_NON_ESISTENTE
        THEN
            DBMS_OUTPUT.PUT_LINE('Cancellamento rifiutato: dipartimento non esistente.');
            RAISE_APPLICATION_ERROR(-20601,'Errore cancellamento di un dipartimento non esistente.');
    END;

----------------------------------

   PROCEDURE valori_iniziali_operatori
   IS
   BEGIN
       INSERT INTO OPERATORI VALUES(idOpe_seq.NEXTVAL, 'Pietro', 'Tornindietro',
                                    1, 'Pompiere');
       INSERT INTO COMPETENZE VALUES(idOpe_seq.CURRVAL, 'Scienze Motorie');

       INSERT INTO OPERATORI VALUES(idOpe_seq.NEXTVAL, 'Maria', 'Salvarezza',
                                    2, 'Infermiere');
       INSERT INTO COMPETENZE VALUES(idOpe_seq.CURRVAL, 'Infermieristica');

       INSERT INTO OPERATORI VALUES(idOpe_seq.NEXTVAL, 'Federica', 'Varlese',
                                    3, 'Poliziotto');
       INSERT INTO COMPETENZE VALUES(idOpe_seq.CURRVAL, 'Diploma scuola secondaria di secondo grado');

       -- Operatore con due titoli di studio
       INSERT INTO OPERATORI VALUES(idOpe_seq.NEXTVAL, 'Fabio', 'Cristalli',
                                    4, 'Carabiniere');
       INSERT INTO COMPETENZE VALUES(idOpe_seq.CURRVAL, 'Perito Agrario');
       INSERT INTO COMPETENZE VALUES(idOpe_seq.CURRVAL, 'Lettere');

       INSERT INTO OPERATORI VALUES(idOpe_seq.NEXTVAL, 'Umberto', 'Pirozzi',
                                    5, 'Maresciallo di Finanza');
       INSERT INTO COMPETENZE VALUES(idOpe_seq.CURRVAL, 'Scienze Politiche');

       INSERT INTO OPERATORI VALUES(idOpe_seq.NEXTVAL, 'Vittorio', 'Solombrino',
                                    6, 'Artificiere');
       INSERT INTO COMPETENZE VALUES(idOpe_seq.CURRVAL, 'Ingegneria meccanica');
    END;

-----------------------------------

    PROCEDURE insert_operatore(
        InNome IN VARCHAR2,
        InCognome IN VARCHAR2,
        InSpecTitolo VARCHAR2,
        InIDDip NUMBER,
        InRuolo IN VARCHAR2
    )
    IS
    BEGIN
        INSERT INTO OPERATORI VALUES(idOpe_seq.NEXTVAL, InNome, InCognome,
                                     InIDDip, InRuolo);
        INSERT INTO COMPETENZE VALUES(idOpe_seq.CURRVAL, InSpecTitolo);
    END;

-----------------------------------
-- Inserisce nella tabella titoli di studio il valore della specializzazione in input
    PROCEDURE insert_titolo(
        InSpecializzazione IN TITOLIDISTUDI.Specializzazione%TYPE -- Prende il tipo dato nella sua dichiarazione
    )
    IS
    BEGIN
        INSERT INTO TITOLIDISTUDI VALUES(InSpecializzazione);
    END;

-----------------------------------
-- Inserisce nella tabella operatore il titolo di studio attaraverso la tabella competenze
    PROCEDURE insert_nuovo_titolo_operatore(
        InIDOpe IN NUMBER,
        InSpecTitolo IN VARCHAR2
    )
    IS
    BEGIN
        INSERT INTO COMPETENZE VALUES(InIDOpe, InSpecTitolo);
    END;

-----------------------------------

    PROCEDURE stampa_operatori
    IS
        CURSOR cursore IS SELECT * FROM OPERATORI;
        record cursore%ROWTYPE;
        counter number:=0;
    BEGIN
        OPEN cursore;
        DBMS_OUTPUT.PUT_LINE('Tabella OPERATORI');
        LOOP
            counter := counter + 1;
            FETCH cursore INTO record;
            EXIT WHEN cursore%NOTFOUND;
            DBMS_OUTPUT.PUT_LINE('Riga n# '  || counter);
            DBMS_OUTPUT.PUT_LINE('  ID: '               || record.ID);
            DBMS_OUTPUT.PUT_LINE('  Nome: '             || record.Nome);
            DBMS_OUTPUT.PUT_LINE('  Cognome: '          || record.Cognome);
            DBMS_OUTPUT.PUT_LINE('  ID dipartimento: '  || record.IDDip);
            DBMS_OUTPUT.PUT_LINE('  Ruolo: '            || record.Ruolo);
            DBMS_OUTPUT.PUT_LINE('');
            END LOOP;
        CLOSE cursore;
    END;

-----------------------------------

    PROCEDURE delete_operatore(
        InID IN OPERATORI.ID%TYPE
    )
    IS
        -- variabile per la verifica dell'esistenza dell'operatore
        operatore_presente NUMBER := 0;
        -- dichiarazione dell'eccezione
        OPERATORE_NON_ESISTENTE EXCEPTION;
    BEGIN
        SELECT COUNT(*) INTO operatore_presente FROM OPERATORI O
                        WHERE O.ID = InID;
        IF (operatore_presente = 0)
        THEN
            RAISE OPERATORE_NON_ESISTENTE;
        END IF;
        -- operatore trovato correttamente
        DELETE FROM OPERATORI WHERE (ID = InID);
    EXCEPTION
        WHEN OPERATORE_NON_ESISTENTE
        THEN
            DBMS_OUTPUT.PUT_LINE('Cancellamento rifiutato: operatore non esistente.');
            RAISE_APPLICATION_ERROR(-20602,'Errore cancellamento di un operatore non esistente.');
    END;

-----------------------------------

     PROCEDURE delete_titolo(
        InSpecializzazione IN TITOLIDISTUDI.Specializzazione%TYPE
    )
    IS
        -- variabile per la verifica dell'esistenza del titolo di studi
        titolo_presente NUMBER := 0;
        -- dichiarazione dell'eccezione
        TITOLO_NON_ESISTENTE EXCEPTION;
    BEGIN
        SELECT COUNT(*) INTO titolo_presente FROM TITOLIDISTUDI T
                        WHERE T.Specializzazione = InSpecializzazione;
        IF (titolo_presente = 0)
        THEN
            RAISE TITOLO_NON_ESISTENTE;
        END IF;
        -- titolo di studi trovato correttamente
        DELETE FROM TITOLIDISTUDI WHERE (Specializzazione = InSpecializzazione);
    EXCEPTION
        WHEN TITOLO_NON_ESISTENTE
        THEN
            DBMS_OUTPUT.PUT_LINE('Cancellamento rifiutato: titolo non esistente.');
            RAISE_APPLICATION_ERROR(-20603,'Errore cancellamento di un titolo non esistente.');
    END;

----------------------------------

    PROCEDURE insert_segnalazione(
        InNumTelefonicoUtente IN SEGNALAZIONI.NumTelefonicoUtente%TYPE,
        InTipologiaEmergenza IN SEGNALAZIONI.TipologiaEmergenza%TYPE,
        InProvincia IN SEGNALAZIONI.Provincia%TYPE,
        InCittà IN SEGNALAZIONI.Città%TYPE,
        InCAP IN SEGNALAZIONI.CAP%TYPE,
        InVia IN SEGNALAZIONI.Via%TYPE,
        InNumeroCivico IN SEGNALAZIONI.NumeroCivico%TYPE,
        InData_Ora IN SEGNALAZIONI.Data_Ora%TYPE
    )
    IS
    BEGIN
        INSERT INTO SEGNALAZIONI VALUES(codSeg_seq.NEXTVAL, InTipologiaEmergenza,
                                        InNumTelefonicoUtente, InProvincia,
                                        InCittà, InCAP, InVia, InNumeroCivico,
                                        InData_Ora);
    END;

-----------------------------------

-- Viene dato in ingresso il codice della segnalazione e all'int della procedure vengono stampate tutte le out
    PROCEDURE informazioni_segnalazione(
        InCodiceSegnalazione IN SEGNALAZIONI.Codice%TYPE,
        OutTipologiaEmergenza OUT SEGNALAZIONI.TipologiaEmergenza%TYPE,
        OutProvincia OUT SEGNALAZIONI.Provincia%TYPE,
        OutCittà OUT SEGNALAZIONI.Città%TYPE,
        OutCAP OUT SEGNALAZIONI.CAP%TYPE,
        OutVia OUT SEGNALAZIONI.Via%TYPE,
        OutNumeroCivico OUT SEGNALAZIONI.NumeroCivico%TYPE,
        OutData_Ora OUT SEGNALAZIONI.Data_Ora%TYPE
    )
    IS
    BEGIN
        SELECT S.TipologiaEmergenza, S.Provincia, S.Città, S.CAP, S.Via, S.NumeroCivico, S.Data_Ora
        INTO OutTipologiaEmergenza, OutProvincia, OutCittà, OutCAP, OutVia, OutNumeroCivico, OutData_Ora
        FROM SEGNALAZIONI S
        WHERE S.Codice = InCodiceSegnalazione;

        -- stampa risultato del join
        DBMS_OUTPUT.PUT_LINE('INFORMAZIONI RELATIVE ALLA SEGNALAZIONE NUMERO ' || InCodiceSegnalazione || ':');
        DBMS_OUTPUT.PUT_LINE('  Tipologia emergenza: ' || OutTipologiaEmergenza);
        DBMS_OUTPUT.PUT_LINE('  Provincia: ' || OutProvincia);
        DBMS_OUTPUT.PUT_LINE('  Città: ' || OutCittà);
        DBMS_OUTPUT.PUT_LINE('  CAP: ' || OutCAP);
        DBMS_OUTPUT.PUT_LINE('  Via: ' || OutVia);
        DBMS_OUTPUT.PUT_LINE('  Numero civico: ' || OutNumeroCivico);
        DBMS_OUTPUT.PUT_LINE('  Data e ora: ' || OutData_Ora);
    END;


-----------------------------------

    PROCEDURE insert_coinvolgimento(
        InIDDip IN COINVOLGIMENTI.IDDip%TYPE,
        InCodSegnalazione IN COINVOLGIMENTI.CodSegnalazione%TYPE
    )
    IS
    BEGIN
        INSERT INTO COINVOLGIMENTI VALUES (InIDDip, InCodSegnalazione);
    END;

-----------------------------------

    PROCEDURE stampa_titoli
    IS
        CURSOR cursore IS SELECT * FROM TITOLIDISTUDI;
        record cursore%ROWTYPE;
        counter number:=0;
    BEGIN
        OPEN cursore;
        DBMS_OUTPUT.PUT_LINE('Tabella TITOLIDISTUDI');
        LOOP
            counter := counter + 1;
            FETCH cursore INTO record;
            EXIT WHEN cursore%NOTFOUND;
            DBMS_OUTPUT.PUT_LINE('Riga n# '             || counter);
            DBMS_OUTPUT.PUT_LINE('  Specializzazione: ' || record.Specializzazione);
            DBMS_OUTPUT.PUT_LINE('');
            END LOOP;
        CLOSE cursore;
    END;

-----------------------------------

    PROCEDURE stampa_segnalazioni
    IS
        CURSOR cursore IS SELECT * FROM SEGNALAZIONI;
        record cursore%ROWTYPE;
        counter number:=0;
    BEGIN
        OPEN cursore;
        DBMS_OUTPUT.PUT_LINE('Tabella SEGNALAZIONI');
        LOOP
            counter := counter + 1;
            FETCH cursore INTO record;
            EXIT WHEN cursore%NOTFOUND;
                DBMS_OUTPUT.PUT_LINE('Riga n# '                 || counter);
            DBMS_OUTPUT.PUT_LINE('  Codice: '                   || record.Codice);
            DBMS_OUTPUT.PUT_LINE('  Tipologia emergenza: '      || record.TipologiaEmergenza);
            DBMS_OUTPUT.PUT_LINE('  Numero telefonico utente: ' || record.NumTelefonicoUtente);
            DBMS_OUTPUT.PUT_LINE('  Provincia: '                || record.Provincia);
            DBMS_OUTPUT.PUT_LINE('  Città: '                    || record.Città);
            DBMS_OUTPUT.PUT_LINE('  CAP: '                      || record.CAP);
            DBMS_OUTPUT.PUT_LINE('  Via: '                      || record.Via);
            DBMS_OUTPUT.PUT_LINE('  Numero civico: '            || record.NumeroCivico);
            DBMS_OUTPUT.PUT_LINE('  Data e ora: '               || record.Data_Ora);
            DBMS_OUTPUT.PUT_LINE('');
            END LOOP;
        CLOSE cursore;
    END;

-----------------------------------

    PROCEDURE stampa_storico
    IS
        CURSOR cursore IS SELECT * FROM STORICO_SEGNALAZIONI;
        record cursore%ROWTYPE;
        counter number:=0;
    BEGIN
        OPEN cursore;
        DBMS_OUTPUT.PUT_LINE('Tabella STORICO_SEGNALAZIONI');
        LOOP
            counter := counter + 1;
            FETCH cursore INTO record;
            EXIT WHEN cursore%NOTFOUND;
                DBMS_OUTPUT.PUT_LINE('Riga n# '                 || counter);
            DBMS_OUTPUT.PUT_LINE('  Codice: '                   || record.Codice);
            DBMS_OUTPUT.PUT_LINE('  Numero telefonico utente: ' || record.NumeroDiTelefono);
            DBMS_OUTPUT.PUT_LINE('  Nome: '                     || record.Nome);
            DBMS_OUTPUT.PUT_LINE('  Cognome: '                  || record.Cognome);
            DBMS_OUTPUT.PUT_LINE('  Tipologia emergenza: '      || record.TipologiaEmergenza);
            DBMS_OUTPUT.PUT_LINE('  Provincia emergenza: '      || record.Provincia);
            DBMS_OUTPUT.PUT_LINE('  Città emergenza: '          || record.Città);
            DBMS_OUTPUT.PUT_LINE('  CAP emergenza: '            || record.CAP);
            DBMS_OUTPUT.PUT_LINE('  Via emergenza: '            || record.Via);
            DBMS_OUTPUT.PUT_LINE('  Numero civico emergenza: '  || record.NumeroCivico);
            DBMS_OUTPUT.PUT_LINE('  Data e ora emergenza: '     || record.Data_Ora);
            DBMS_OUTPUT.PUT_LINE('');
            END LOOP;
        CLOSE cursore;
    END;

-----------------------------------

    PROCEDURE stampa_competenze
    IS
        CURSOR cursore IS SELECT * FROM COMPETENZE;
        record cursore%ROWTYPE;
        counter number:=0;
    BEGIN
        OPEN cursore;
        DBMS_OUTPUT.PUT_LINE('Tabella COMPETENZE');
        LOOP
            counter := counter + 1;
            FETCH cursore INTO record;
            EXIT WHEN cursore%NOTFOUND;
                DBMS_OUTPUT.PUT_LINE('Riga n# '        || counter);
            DBMS_OUTPUT.PUT_LINE('  ID operatore: '    || record.IDOpe);
            DBMS_OUTPUT.PUT_LINE('  Titolo di studi: ' || record.SpecTitolo);
            DBMS_OUTPUT.PUT_LINE('');
            END LOOP;
        CLOSE cursore;
    END;

-----------------------------------

END PACK_SEN;
