// JavaScript Document

/*
 * Umożliwia wysłanie zapytania i wprowadza
 * odpowiednią do wskazanego elementu ID
 * lub uzyskanego w odpowiedzi jako nazwą taga korzennego
 */


/**
 * DestSender
 * 
 * Należałoby dorobić jeszcze aby defResponse wywoływane było jeszcze
 * z innej fukcji, która spełni podstawowe założnenia systemu, czyli 
 * obsłuży listenera oraz byc może sprawdzenie poprawności. 
 * Może zrobić wiele listenerów oraz 
 * 
 * Parametry
 * @param destination - id elementu, do którego nalezy wprowadzić odpowiedź
 *        ewentualnie konkretny obiekt HTML do którego należy wsadzić zawartość 
 * @param http_method - metoda przesłania danyc GET lub POST
 *
 * @version 4.11
 */
function DestSender(destination, http_method) {
    
    var instance = this;
    if (!http_method) http_method = "GET";
   
    DestSender.prototype.request = new Asynchronous(http_method);

    /**
     * Funkcja obsługująca odpowiedą z serwera
     * oraz wstawia do odpowiedniego miejsca
     * wskazanego w konstruktorze lub wskazanego
     * w odpowiedzi. W przypadku różnych mniejdc
     * priorytetowym jest...
     */
    var defResponse =
    function (status, statusText, responseText, responseXML, sender) {

        //        alert("Odczytane: " + responseText);
        //        alert("Odczytane: " + responseXML.firstChild.firstChild.firstChild.data);


        /* sprawdzenie warunków poprawnego odbioru */

        if (instance.errorHandler) instance.errorHandler(status, statusText);

        /* poinformowanie listenera o odczytaniu informacji
         * i ewentualne zatrzymanie aksji
         */

        if (instance.listener) {
            var nobreak = instance.listener(responseText, responseXML, instance);
            if (!nobreak) return;
        }

        if (responseXML == null || !responseXML.hasChildNodes()) {
            if (instance.emptyAlert)
            alert("Rozpacz!!! " + instance.emptyAlert);
            return;
        }

        
        /* PRZEGLĄDANIE ZAWARTOŚCI PRZESYŁKI */
        
        /* przeszukiwanie polega na przeglądzie po wszystkich
         * elekentach view oraz wybraniu z nich atrybutów:
         * - dest - cel przesyłki 
         * - method - metoda wrzucania 
         */
        
        var views = responseXML.getElementsByTagName('view');
                
        if (!views.length) {
            alert("Rozpacz!!! Nie ma żadnych widoków:\n\r" + responseText);
            return;
        }

        var destName = "";
        var method = null;
        
        /* tablica będzie przechowywać zawartość do wstawienia
         * dla poszczególnych celów wskazywanych przez klucz tablicy */
        var targets = new Array();
        
        /* sprawdzenie, czy predefiniowano */
        
        if (instance.destID) {
            if (instance.destID.nodeName) destName = instance.destID;
        }

        if (instance.insertMethod) {
            method = instance.insertMethod;
        }

        /* Pętla po ele,entach view */

        for (var i = 0; i < views.length; i++) {
            var view = views[i];

            var dn = view.getAttribute('dest');
            if (dn && !instance.ignoreServerDest) destName = dn;
            
            if (!instance.insertMethod) {
                method = view.getAttribute("method");
            }

            /* Pobranie wszystkich nodów dla view
             * i odpowiednia obsługa zawartości
             * alert('Nazwa nody to: ' + tags[tagIndex].nodeName + ' => ' + tags[tagIndex].nodeType );
             */
            var tags = view.childNodes;

            var wsad = "";
            el(destName).innerHTML = "";
            var scriptRunner = loaderFactory.createJScriptRunner();
            var styleLoader = loaderFactory.createStyleLoader(destName);

            for (var tagIndex = 0; tagIndex < tags.length; tagIndex++) {

                var tag = tags[tagIndex];
                
                switch(tag.nodeName) {

                    case 'script':

                        /* scrypt jest w zawartości czy linku ? */
                        scriptRunner.loadJScript(tag);
                        
                        break;

                    case 'style':
                    case 'link':

                        /* style są w zawartości czy linku ? */
                        styleLoader.loadStyle(tag);
                        break;

                    case '#cdata-section':
//                        alert('Zawartość HTML: ' + tag.data);
                        wsad = tag.data;
                        break;

                    default:
//                        alert('Nic tu nie ma: ' + tag.nodeValue);

                }
              
            }
            
            /* wybór metody wstawienia obrazka */
            switch (method) {

                case 'tableRow':
                    alert('Wstawianie tableRow - niezimplementowane');
                    break;

                case 'appendChild':
                    alert('Wstawianie appendChild - niezimplementowane');
                    break;

                case 'insertBefore':
                    alert('Wstawianie insertBefore - niezimplementowane');
                    break;

                default:
                    if (!targets[destName]) targets[destName] = "";
                    if (destName) targets[destName] += wsad;
                    else alert("Rozpacz!!! Nie ma celu dla:\n\r" + wsad);
            }

            /* wszystko jest już wpisane, można zgłosić runnerowi, że OK */
            scriptRunner.itsAll();
            styleLoader.itsAll();
        }
        
        /* wstawienie do właściwego elementu */
        
        for(var target in targets) {
            var desthtml = el(target);
            if (desthtml) desthtml.innerHTML += targets[target];
            else alert("Rozpacz!!! Nie ma elementu:\n\r" + target);
        }
    }
 
    
    this.setResponseFunction(defResponse);
    this.destID = destination;
    this.ignoreServerDest = false;
    this.insertMethod = null;
}


/**
* Wysyła zapytanie pod wskazany adres w url
* jako drugi parametr można podać tablicę asocjacyjną
* z parametrami wysyłki
*/
function DestSender_send(url, paramsArray, content) {
    var params = '';

    if (paramsArray)
        for (var paramName in paramsArray)
            params += '&' + paramName + '=' + paramsArray[paramName];


    /* Sprawdzenie, czy url, nie zawiera już separatora parametrów */
    var paramSep = '';
    if (url.indexOf('?') == -1) paramSep = '?';
    
    if (this.response !== null)
        this.request.call(url + paramSep + params, content);
}

/* Domyślna funkcja listenera nicnierobiąca i pozwalająca na dalszy 
 * bieg domyślej funkcji response
 */
function DestSender_listener(responseText, responseXML, sender) {
    return true;
}

/* funkcja otrzynująca odpowedź żądania */
DestSender.prototype.setResponseFunction = 
    function(respFunction) {
        this.request.complete = respFunction;
        return this;
    }


/* ****************************************************
* Definicje funckji ustawiających wstawianie 
* wymuszają one jednocześnie wstawianie za pomocą XML,
* a nie responseText i innerHTML
*/

/* Ustawia wstawianie przed wskazanym dzieckie elementu
* parametrem może być id elementu lub sam element */
DestSender.prototype.setInsertBefore = function(parentNode, childNode) {
    this.insertMethod = "insertBefore";
    this.insertParams = new Array(parentNode, childNode);
}


/* Ustawia wstawianie za ostatnim dzieckiem elementu
* parametrem może być id elementu lub sam element */
DestSender.prototype.setAppendChild = function(parentNode) {
    this.insertMethod = "appendChild";
    this.insertParams = new Array(parentNode);
}



/* Ustawia wstawianie przed wskazanym wierszem wskazanej tabeli 
* parametrem może być tabela lub id tabeli oraz numer wiersza 
* 0 - wstawia na początek, brak parametru jako ostatni wiersz */
DestSender.prototype.setInsertTableRow = function(table, rowNumber) {
    this.insertMethod = "tableRow";
    this.insertParams = new Array(table, rowNumber);
}

/**
* Poprawić należy te funkcje aby umożliwiała rzeczywiście
* zamianę ewentulanych stringów na obiekty html */
DestSender.prototype.getElement = function(element) {
    return element;
}


DestSender.prototype.request = null;

/**
 * funckja wywoływna po otrzymaniu odpowiedzi 
 * jeśli zwróci nieprawdę nie bedzie wykonywane wstawianie 
 */
DestSender.prototype.listener = null;


/**
 * Funkcja służy do wyłapywania błędów
 * podczas odbioru odpowiedzi
 */
DestSender.prototype.errorHandler = function(status, statusText) {
    if (status != '200') {
        alert("Rozpacz!!! Błąd serwera: " + statusText);
        return;
    }
}



/**
 * Meotda zapamiętuje atrybuty o podanym kluczu, które mogą być potem 
 * odtworzone p otrzymaniu przesyłki. Można służyć do zapajmiętania
 * przycisku, który wykonał akcję ajax
 */
DestSender.prototype.store = function(key, value) {
    if (!this.memory) this.memory = new Array();
    this.memory[key] = value;
}

DestSender.prototype.save = DestSender.prototype.store;


/**
 * Meotda odtwearza warto9ści zapamiętane operacją save
 */
DestSender.prototype.restore = function(key) {
    if (this.memory) return this.memory[key];
    else return null;
}


/**
 * Dla wartości parametru true, ignorowane sa zawartości
 * podesłane przez serwer
 */
DestSender.prototype.setIgnoreServerDest = function(ignore) {
    this.ignoreServerDest = ignore;
}


/* dwie funkcje stanowiące to samo, czyli wysłanie żądania */
DestSender.prototype.send = DestSender_send;
DestSender.prototype.get = DestSender_send;

/* Ustawienie tego paramtru powoduje wyświetlanie informacji
 * jeśli przesyłka powróci pusta */
DestSender.prototype.emptyAlert = null;
