/***

    CAMAO Adsense Klasse zum verwalten von Google Werbung (c) CAMAO 2009
    V0.1 - v2.3.0c Matthias Friedrich

    Beschreibung :
    Dieses Script verarbeitet und verwaltet die komplette Adsense Ausgabe auf der Webseite.
    Durch Angaben von Benutzer definierten Keywords ist es moeglich gezielt Werbung anzufragen.
    Liefert Google mit einem Keyword keine Werbung kann man ein 'Fallback' Keyword angeben,
    sollte auch hier keine Werbung kommen, ist es auch moeglich den Container, mit HTML
    Code zu fuellen bzw falls kein HTML Code hinterlegt wurde, den Container zu entfernen.
    Unterschiedliche Zonen durch unterschiedlichen Channel IDs und Keywords mit Werbung
    zu fuellen ist auch moeglich.
    
    Generelle Info :
    Es wird ein Adsense Premium Pub-ID benoetigt!

    Changelog :
    17.08.2009  Recode des Codes
    19.08.2009  Code Cleanup (debug ausgaben in funktion zusammen gefasst)
            Template auswahl variable gestaltet
            AFC als Fallback eingestellt
            Dokumentation erweitert

    26.08.2009  Korrektur der Sprach ueberpruefung
                AFS Fallback Fix (Google antwort wurde nicht richtig interpretiert)

    27.08.2009  getErrorLog eingebaut

    28.08.2009  Google Test im debug mode aktiviert
    31.08.2009  Single Adsense fallback eingebaut
    07.09.2009  Single Adsense remove bugfixes
    08.09.2009  Single Box Adsense remove bugfix
                IE8 append Template bugfix
    09.09.2009  Content regex camelcase problem fix
                Fallback wahlweise aktivier / deaktivier bar gemacht
                Fallback remove container bug behoben

    10.09.2009  Google-Anzeigen text mit target blank versehn

    11.09.2009 New Template number 5
    28.10.2009 Add skip parameter
    05.11.2009 onLoad Event handling
    14.01.2010 afc / afs feedback url fix
    15.01.2010 Error handling
    08.02.2010 indexOf 'bugfix' (not realy a fix in this script, its a fix for the iP board! the board handles the objs wrong, so we make a workaround....
    09.02.2010 domReady event um einen timeout 0 verzögert
    29.03.2010 allow_fallback default to false
    30.03.2010 this.up function bugfix, wrong handling with the parentNode
    31.03.2010 add image support
    08.04.2010 add en as language
    09.04.2010 add new template 10, add new languages
    21.04.2010 add template handling , allow to set the template id inside the class attibute of the element
    26.04.2010 fixing a dom loaded bug for ie8
    27.05.2010 add new template 11

    @Todos :
    - Pruefen ob der onload Event schneller sein kann als die Antworten von Google

    Class Instruktionen
    ############################

    Initialisierung
    (bool) camaoAdsenseObj.init(options);                                   
    
    Note : Es ist von vorteil wenn dieses Init-Script so frueh wie moeglich ausgefuehrt wird!
    Pflicht Optionen 
    pubid               Google Adsense PUB-ID                       (string)
    *keyword            Beliebiges Keyword (Auto, Haus, Liebe ....)         (string)
    part1               Einstellungen fuer Zone 1                   (object)
        *keyword            Beliebiges Keyword (Auto, Haus, Liebe ....)         (string)
        type            Ausgaben Type, afs oder afc oder afc_image (for search / for content / for content with image)      (string)
        image_size      Bestimmt die anzeige groesse fuer den type afc_image
        container           Container fur die Ausgaben Einstellungen            (array[object])
        [elementID]     Bestimmt das Element an dem Werbung erscheinen soll     (object)

        Note : der [elementID] Teil sowie part1 kann beliebig oft wiederholt werden.

    * Gibt man das Keyword in der obersten Ebene an , bezieht sich das auf alle Zonen
      Gibt man das Keyword in der Zonen Ebene an, bezieht sich das nur auf diese Zone

    Moegliche Optionen
    language            Gibt die Sprache der Werbung an (de,hu,ro,...)          (string)
    *template           Legt fest welches Template verwendet werden soll        (integer)
    part1               Siehe Pflicht Optionen
        fallback_keyword        Falls Google mit dem Primaeren Keyword keine Werbung liefert,
                    wird versucht mit diesem Keyword Werbung zu holen.

                    Note : das fallback_keyword verursacht ein nachladen der Werbung von Google

        hints           Gibt Google hilfe stellung bei der findung von Werbung,
                    hier wird perkomma getrennt die keywords uebergeben     (string)

        channel         Google Adsense Channel ID                   (string)
        *template           Legt fest welches Template verwendet werden soll        (integer)
        container           Siehe Pflicht Optionen
        *template       Legt fest welches Template verwendet werden soll        (integer)
                    kann hier ein ersatz keyword angegeben werden.
        [elementID]     Siehe Pflicht Optionen
            fallback_html   Falls Google mit dem Primaeren und Secondary (falls angegeben)
                    Keyword keine Werbung liefert, kann hier eine HTML Alternative
                    angegeben werden                        (string)

    * Gibt man das template in der obersten Ebene an , bezieht sich das auf alle Zonen
      Gibt man das template in der Zonen Ebene an, bezieht sich das nur auf diese Zone

    Sonstiges 
    adsenseItemOver         Ist eine CSS Class die bei onmouseover geadded wird
                    und bei onmouseout entfernt wird

    ############################


    Aufruf Beispiel :
    ############################

    camaoAdsenseObj.init({ 
    'pubid' : 'pub-5734750340876442',
    'keyword' : 'adsense',
    'part1' : {
        'type' : 'afc',
        'container' : [{
            'template' : 1,
            'adsense1' : {}
        }]
    },
    'part2' : {
        'type' : 'afc',
        'keyword' : 'kleidung',
        'container' : [{
            'template' : 2,
            'adsense2' : {}
        },{
            'template' : 2,
            'adsense3' : {}
        }]
    }
    });

    ############################

***/
var alreadyrunflag;
var oldOnload = function(){};

function camaoAdsense(){
    var ads = { 'callcount' : 0, 'recived' : [], 'noAds' : {'container':[], 'element' : [] }, 'futureCalls' : [] };
    var fallbacks = { 'language' : 'de' };
    var settings = { 'codierung' : 'utf8', 'usedTemplates' : [false, false, false,false,false,false,false,false,false,false,false], 'usedTemplatesPartType' : [false, false, false,false,false,false,false,false,false,false,false], 'lastdoubleclicksurl' :  '', 'domReady' : false, 'defaultTemplate' : 1, 'hoverclass' : "adsenseItemOver"};
    var blockedAdsense = false;
    var singleAdRequest = false;
    var activeAdsenseLoop = 1;
    var errorLog = "";

    this.init = function(options){
    try{
        useddoc = this.getDocumentHandler();
        ads.options = options;

        if (typeof ads.options.allow_fallback == "undefined"){
            ads.options.allow_fallback = false;
        }

        //Falls keine Sprache festgelegt wurde, wird die sprache anhand der Domain festgelegt
        if (!ads.options.language){
            if(window.location.host){
                hostname = window.location.host.split(".");
                switch(hostname[hostname.length - 1]){
                    case 'com':
                        hostname = fallbacks.language;
                        this.debug("Warning, com domain detected , use language " + fallbacks.language + "!");
                    break;
                    case 'org':
                        hostname = fallbacks.language;
                        this.debug("Warning, org domain detected , use language " + fallbacks.language + "!");
                    break;
                    case 'net':
                        hostname = fallbacks.language;
                        this.debug("Warning, net domain detected , use language " + fallbacks.language + "!");
                    break;
                    default :
                        hostname = fallbacks.language;
                }
                ads.options.language = hostname || fallbacks.language;
            }else{
                ads.options.language = fallbacks.language;
            }
            this.debug("init : Set Language to " + ads.options.language);
        }
        
        //Wir vordern die erste Werbung an
        this.getNextAdsense();

        //Wir warten mit dem Onload Event bis der Dom unsere elemente fertig geladen hat
        this.createOnloadEvent();
        return true;
    }catch(e){ return false;}
    }

    //Wir erstellen den Onload Event
    this.createOnloadEvent = function(){
        if (document.addEventListener) document.addEventListener("DOMContentLoaded", function(){alreadyrunflag=1; window.setTimeout("camaoAdsenseObj.domReadyEvent()",0);}, false)
        else if (document.all && !window.opera){
            document.write('<script type="text/javascript" id="contentloadtag" defer="defer" src="javascript:void(0)"><\/script>');
            var contentloadtag = document.getElementById("contentloadtag");
            contentloadtag.onreadystatechange = function(){
                if (this.readyState=="complete"){
                    alreadyrunflag=1;
                    if(navigator.userAgent.indexOf("MSIE 8.0") != -1){
                        window.setTimeout("camaoAdsenseObj.domReadyEvent();", 1000);
                    }else{
                        window.setTimeout("camaoAdsenseObj.domReadyEvent();", 0);
                    }
                }
            }
        }

        if (window.onload != undefined){
            oldOnload = window.onload;
        }

        window.onload=function(){ setTimeout("if (!alreadyrunflag) camaoAdsenseObj.domReadyEvent()", 0); oldOnload(); }
    }

    //Fordert die naechste Werbung anhand der Zone an
    this.getNextAdsense = function(){
        eval("part = ads.options.part" + activeAdsenseLoop + " || false;"); 
        if (part != false){
            this.debug("getNextAdsense : Using this Part :");
            this.debug("######");
            this.debug(part);
            this.debug("######");

            part.fallback = false;
            blockedAdsense = true;

            //Google resetet die Variablen , daher muesen wir sie immer wieder belegen
            this.createDefaultScript(part);
            this.createCallScript(part);
            this.getAdsense();
            activeAdsenseLoop++;
        }


        if(ads.futureCalls.length > 0){
            blockedAdsense = true;
            this.debug("getNextAdsense : Found a call outside the Parts:");
            part = ads.futureCalls[0];
            this.createDefaultScript(part);
            this.createCallScript(part);
            this.getAdsense();
            ads.futureCalls.shift();
        }
    }

    //Wird ausgeloest wenn der DOM Fertig ist
    this.domReadyEvent = function(){
        this.createUsedTemplates();
        this.insertAdsense();
        settings.domReady = true;
    }

    //Erstellt die Default Variablen fuer die Werbung
    this.createDefaultScript = function(part){
        adtype = part.type || "afc";

        if (part.fallback == false){
            ads.output = "\n<script type='text/javascript'>";
        }else{
            ads.output = "";
        }

        if (ads.options.debug){ 
            ads.output += "\n" + "google_adtest = 'ON';";
        }

        ads.output += "\n" + "google_ad_output = 'js'";
        ads.output += "\n" + "google_feedback = 'on';";
        ads.output += "\n" + "google_language = '" + ads.options.language + "';";
        ads.output += "\n" + "google_encoding = '" + settings.codierung + "';";

        if ((adtype == "afc") || (adtype == "afc_image")){
            ads.output += "\n" + "google_ad_client = '" + ads.options.pubid + "';";
          //ads.output += "\n" + "google_ad_oe = '" + settings.codierung + "';";
          //  ads.output += "\n" + "google_ad_section = 'default';";
        }else{
            ads.output += "\n" + "google_afs_client = '" + ads.options.pubid + "';";
            ads.output += "\n" + "google_afs_oe = '" + settings.codierung + "';";
            ads.output += "\n" + "google_afs_hl = '" + ads.options.language + "';";
            ads.output += "\n" + "google_afs_gl = '" + ads.options.language + "';";
            ads.output += "\n" + "google_afs_adsafe = 'high';";
        }

        if (adtype == "image"){
            ads.output += "\n" + "google_ad_type = 'text_image';";
        }

        if (part.fallback == false) ads.output += "\n</script>";
    }

    //Erstellt die Zonen Variablen fuer die Werbung
    this.createCallScript = function(part){
        adtype = part.type || "afc";

        if (part.fallback == false) ads.output += "\n<script type='text/javascript'>";

        if (part.hints){ 
            ads.output += "\n" + "google_hints = '" + part.hints + "';";
        } else if (ads.options.hints){ 
            ads.output += "\n" + "google_hints = '" + ads.options.hints + "';";
        }

        if (part.skip){ 
            ads.output += "\n" + "google_skip = '" + part.skip + "';";
        }

        if ((adtype == "afc") || (adtype == "afc_image")){
            if (part.channel){ 
                ads.output += "\n" + "google_ad_channel = '" + part.channel + "';";
            } else if (ads.options.channel){ 
                ads.output += "\n" + "google_ad_channel = '" + ads.options.channel + "';";
            }
            if (part.howmany){
                ads.output += "\n" + "google_max_num_ads = '" + (part.howmany) + "';";
            }else{
                ads.output += "\n" + "google_max_num_ads = '" + (part.container.length ) + "';";
            }

            if (part.keyword){
                ads.output += "\n" + "google_kw_type = 'broad';";
                ads.output += "\n" + "google_kw = '" + part.keyword + "';";
            }else{
                if (ads.options.keyword){
                    ads.output += "\n" + "google_kw_type = 'broad';";
                    ads.output += "\n" + "google_kw = '" + ads.options.keyword + "';";
                }
            }
        }else{
            if (part.channel){ 
                ads.output += "\n" + "google_afs_channel = '" + part.channel + "';";
            } else if (ads.options.channel){ 
                ads.output += "\n" + "google_afs_channel = '" + ads.options.channel + "';";
            }
            if (part.howmany){
                ads.output += "\n" + "google_afs_ad = 'w" + (part.howmany) + "';";
            }else{
                ads.output += "\n" + "google_afs_ad = 'w" + (part.container.length) + "';";
            }



            if (part.keyword){
                ads.output += "\n" + "google_afs_query = '" + part.keyword + "';";
            }else{
                if (ads.options.keyword){
                    ads.output += "\n" + "google_afs_query = '" + ads.options.keyword + "';";
                }else{
                    this.debug("createCallScript : Warning, you cant use AFS without Keyword!");
                }
            }
        }
        if (adtype == "afc_image"){
            if (part.image_size){
                ads.output += "\n" + "google_image_size = '" + part.image_size + "';";
                ads.output += "\n" + "google_ad_type = 'text_html';";
            }else{
                this.debug("createCallScript : Warning, you cant use AFC_IMAGE without height and width!");
            }

        }

        if (part.fallback == false) ads.output += "\n</script>";

        if ( (adtype == "afc") || (adtype == "afc_image") ){
            ads.output += '\n<script language="javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>';
        }else{
            ads.output += '\n<script language="javascript" src="http://www.google.com/afsonline/show_afs_ads.js"></script>';
        }
    }


    //Erstellt die benoetigten Templates
    this.createUsedTemplates = function(){
        for (i = 0; i < 10; i++){
            eval("part = ads.options.part" + i + " || false;");
            if (part != false){
                if (ads.options.template){
                    settings.usedTemplates[ads.options.template] = true;
                }
                for (x = 0; x < part.container.length; x++){
                    element = part.container[x];
                    for (var template in element){

                        if(template == "template") {
                            settings.usedTemplates[eval("element." + template)] = true;
                            settings.usedTemplatesPartType[eval("element." + template)] = part.type;
                        }else if(template == "type") {
                            if (template[template] == "afc_image"){
                                settings.usedTemplates[9] = true;
                                settings.usedTemplatesPartType[9] = "afc_image";
                            }
                        }else{
                            if (this.$(template)){
                                if (this.$(template).className.indexOf("__") != -1){
                                    var temp_explode = this.$(template).className.split("__");
                                    var temp_explode2 = temp_explode[1].split("__");
                                    var temp_explode3 = temp_explode2[0].split("_");
                                    var template_number = temp_explode3[1];
                                    settings.usedTemplates[template_number] = true;

                                }
                            }
                        }

                    }

                    if (part.template){
                        settings.usedTemplates[part.template] = true;
                        if (part.type){
                            settings.usedTemplatesPartType[part.template] = part.type;
                        }else{
                            settings.usedTemplatesPartType[part.template] = ads.options.type;
                        }

                        if(part.type) {
                            if (part.type == "afc_image"){
                                settings.usedTemplates[9] = true;
                                settings.usedTemplatesPartType[9] = "afc_image";
                            }
                        }

                    }
                }
            }
        }

        foundActiveTemplate = false;
        for (i = 0; i < settings.usedTemplates.length; i++){ if (settings.usedTemplates[i] != false) foundActiveTemplate = true; }
        if (foundActiveTemplate == false) settings.usedTemplates[settings.defaultTemplate] = true;

        for (i = 0; i < settings.usedTemplates.length; i++){
            if (settings.usedTemplates[i] != false){
                code = this.getTemplate(i);
                this.debug("createUsedTemplates : Write Template Code (" + i + ")");

                useddoc = this.getDocumentHandler();
                newdiv = document.createElement("DIV");
                newdiv.innerHTML = code;
                try{
                    useddoc.appendChild(newdiv);
                }catch(e){
                    useddoc.firstChild.appendChild(newdiv);
                }
            }
        }
    }

    //Gibt die gesammelten Variablen und JS Calls aus
    this.getAdsense = function(){ document.write(ads.output); }

    //Google Adsense Antwort
    this.reciveAdsense = function(google_ads){

        blockedAdsense = false;

        this.debug("reciveAdsense : Reciving Adsense for Part" + ads.callcount + "");
        this.debug("######");
        this.debug(google_ads);
        this.debug("######");


        partLength = 1;
        eval("part = ads.options.part" + (ads.callcount + 1) + " || false;");
        if (part){
            partLength = part.container.length;
        }

        if (singleAdRequest == false){
            //Wir haben garkeine werbung erhalten
            if (google_ads.length == 0){
                this.debug("reciveAdsense : No Ads recived for Part" + ads.callcount + "");
                if (camaoIndexOf(ads.noAds.container,ads.callcount) == -1){
                    ads.noAds.container.push(ads.callcount);
                }
            //Wir haben werbung erhalten aber nicht fuer alle in diesem part
            }else if (google_ads.length  != partLength ){ 
    
                this.debug("reciveAdsense : Not all Adsense recived for Part" + ads.callcount + ", missed " + (partLength - google_ads.length) + " ads");
                if (ads.noAds.container) if (camaoIndexOf(ads.noAds.container,ads.callcount) !== -1) ads.noAds.container[camaoIndexOf(ads.noAds.container,ads.callcount)] = -1;


                if (camaoIndexOf(ads.noAds.element,ads.callcount) == -1){
                    info = {
                        'callcount' : ads.callcount,
                        'missing'   : partLength - google_ads.length,
                        'targets' : [],
                        'ads' : []
                    };
                    ads.noAds.element.push(info);
                }

    
                ads.recived.push({
                    'ads' : google_ads,
                    'callcount' : ads.callcount
                });


            }else{
                this.debug("reciveAdsense : All Adsense recived for Part" + ads.callcount + "):");
                //Im falle des Fallbacks, muessen wir das noAds array cleanen da wir ja jetzt doch werbung haben
                if (ads.noAds.container) if (camaoIndexOf(ads.noAds.container,ads.callcount) !== -1) ads.noAds.container[camaoIndexOf(ads.noAds.container,ads.callcount)] = -1;
    
                ads.recived.push({
                    'ads' : google_ads,
                    'callcount' : ads.callcount
                });
            }
        
            ads.callcount = ads.callcount + 1;
        }else{

            if (google_ads.length == 0){
                this.debug("reciveAdsense : No Ads recived for Part" + ads.callcount + "");
              //  if (ads.noAds.container.indexOf(ads.callcount) == -1){
              //      ads.noAds.container.push(ads.callcount);
              //  }
            }else if (google_ads.length  != singleAdRequest ){ 
                this.debug("reciveAdsense : Not all Adsense recived for Part" + ads.callcount + ", missed " + (singleAdRequest - google_ads.length) + " ads");

    
                for (var i = 0; i < ads.noAds.element.length; i++){
                    node = ads.noAds.element[i];
                    if (node.callcount == ads.callcount){
                        node.ads.push(google_ads);
                    }
                }

            }else{
                this.debug("reciveAdsense : All missed Adsense recived for Part" + ads.callcount + "):");
                //Im falle des Fallbacks, muessen wir das noAds array cleanen da wir ja jetzt doch werbung haben
                if (ads.noAds.element) if (camaoIndexOf(ads.noAds.element,ads.callcount) !== -1) ads.noAds.container[camaoIndexOf(ads.noAds.container,ads.callcount)] = -1;
    
                for (var i = 0; i < ads.noAds.element.length; i++){
                    node = ads.noAds.element[i];
                    if (node.callcount == ads.callcount){
                        node.ads.push(google_ads);
                    }
                }

                ads.recived.push({
                    'ads' : google_ads,
                    'callcount' : ads.callcount
                });

            }
            //Hmm darf ich das hier machen ?!
            ads.callcount = ads.callcount + 1;


        }

        if (settings.domReady == true){
            this.insertAdsense();
        }


    }

    this.insertAdsense = function(){
        //Da das document fertig geladen wurde, kann man diese funktion nicht mehr verwenden, also ueberlagern wir sie
        //Sonst kann google nicht weiter arbeiten ;)
        if (ads.options.allow_fallback == true) {
            document.write = function(param){ camaoAdsenseObj.document_write_overload(param); }
        }

        this.debug("insertAdsense : Inserting Adsense...");

        readyForClean = [];

        ads.useTemplateNumber = "";
        if (ads.recived.length > 0){
            for(var i = 0; i < ads.recived.length; i++){
                recived = ads.recived[i];
                eval("part = ads.options.part" + (recived.callcount + 1) + " || false;"); //(recived.callcount + 1) weil unsere Parts bei 1 anfangen nicht bei 0
                if (part != false){
                    if (ads.options.template){ ads.useTemplateNumber = ads.options.template; }
    
                        for (var x = 0; x < part.container.length; x++){
                            element = part.container[x];
                            if (part.template) ads.useTemplateNumber = part.template;
        
                            for (var target in element){
                                if(target == "template"){
                                    ads.useTemplateNumber =  eval("element." + target);
                                }else{
//                                    if (ads.useTemplateNumber == ""){
                                        if (this.$(target)){
                                            if (this.$(target).className.indexOf("__") != -1){
                                                var temp_explode = this.$(target).className.split("__");
                                                var temp_explode2 = temp_explode[1].split("__");
                                                var temp_explode3 = temp_explode2[0].split("_");
                                                var template_number = temp_explode3[1];
                                                ads.useTemplateNumber = template_number;
            
                                            }else{
                                                if (ads.useTemplateNumber == ""){
                                                    ads.useTemplateNumber = settings.defaultTemplate; 
                                                }
                                            }
                                        }
                                  //  }
                                    if (singleAdRequest == false){
        
                                        node = document.getElementById(target);
                                        if (recived.ads.length != 0){
                                            if (node){
                                                if (recived.ads[x]){
                                                    this.createAdsenseContext(node, recived.ads[x], ads.useTemplateNumber);
                                                }else{
                                                    this.debug("insertAdsense : Missing ad for  : " + target);
                                                    for (var z = 0; z < ads.noAds.element.length; z++){
                                                        noadelement = ads.noAds.element[z];
                                                        if(noadelement.callcount == recived.callcount){
                                                            noadelement.targets.push(target);
                                                        }
                                                    }
            
            
                                                }
                                            }else{
                                                this.debug("insertAdsense : Unknown Target ID : " + target);
                                            }
                                        }
                                        useTemplateNumber = "";
                                    }else{
                                        
                                        for (var m = 0; m < ads.noAds.element.length; m++){
                                            singleAd = ads.noAds.element[m];
    
                                            if (singleAd.callcount == recived.callcount){
                                                for (var n = 0; n < singleAd.targets.length; n++){
                                                    singleTarget = singleAd.targets[n];
    
                                                    if (singleTarget == target){
                                                        this.debug("insertAdsense : Single Target found : " + target);
                                                        if (singleAd.ads[0][n]){
                                                            this.createAdsenseContext(document.getElementById(target), singleAd.ads[0][n], ads.useTemplateNumber);
                                                            if (camaoIndexOf(readyForClean,m) == -1) {
                                                                readyForClean.push(m);
                                                            }
                                                        }else{
                                                            this.debug("insertAdsense : No Adsense found for Single Target : " + target + ", bug?!");
                                                        }
    
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
    
    
                }
    

            }
        }else{
            this.debug("insertAdsense : No normal ads found, looking for missed ads : ");
            for (var m = 0; m < ads.noAds.element.length; m++){
                singleAd = ads.noAds.element[m];
    
                //if (singleAd.callcount == recived.callcount){
                    for (var n = 0; n < singleAd.targets.length; n++){
                        singleTarget = singleAd.targets[n];
                        node = document.getElementById(singleTarget);
    
                   //     if (singleTarget == target){
                            this.debug("insertAdsense : Single Target found : " + singleTarget);
                            if (singleAd.ads[0][n]){
                                this.createAdsenseContext(node, singleAd.ads[0][n], this.getTemplateIDByPart(singleAd.callcount));
                                if (camaoIndexOf(readyForClean,m) == -1) {
                                    readyForClean.push(m);
                                }
                            }else{
                                this.debug("insertAdsense : No Adsense found for Single Target : " + singleTarget + ", bug?!");

                                if (node.innerHTML == ""){
                                    node.parentNode.removeChild(node);
                                }





                            }
    
                     //   }
                    }
                //}
            }
        }

        for (var m = 0; m < readyForClean.length; m++){
            ads.noAds.element[readyForClean[m]] = -1;
        }


        //Wir reseten das array weil wir alles verarbeitet haben was wir zurzeit haben
        ads.recived = new Array();

        // wir sind beim letzten part, jetzt koennen wir schaun ob werbung fehlt
        if (this.countParts() == ads.callcount ){

            for (var i = 0; i < ads.noAds.container.length; i++){
                noAd = ads.noAds.container[i];

                if (noAd != -1){
                    //(noAd + 1) weil unsere Parts bei 1 anfangen nicht bei 0
                    eval("part = ads.options.part" + (noAd + 1) + " || false;"); 
                    if (part != false){
                        this.debug("insertAdsense : No Adsense recived for Part" + (noAd));

                        if ( (part.fallback_keyword) && (ads.options.allow_fallback == true) ){
                            this.debug("insertAdsense : Using fallback keyword " + part.fallback_keyword);
        
                            ads.callcount = 0;
                            part.keyword = part.fallback_keyword;
                            part.fallback_keyword = "";
                            part.fallback = true;
                            ads.futureCalls.push(part);
                            if (blockedAdsense == false) this.getNextAdsense();

                        }else{
                            //Wir haben kein fallback keyword gefunden also schaun wir nach
                            //dem HTML Fallback oder entfernen den container
                            for (var x = 0; x < part.container.length; x++){
                                element = part.container[x];
                                for (var target in element){
                                    if(target != "template"){

                                        node = document.getElementById(target);
                                        fallback_html = eval("part.container[x]." + target + ".fallback_html");
                                        if (fallback_html){
                                            this.debug("insertAdsense : Using fallback HTML");
                                            node.innerHTML = fallback_html;
                                        }else{
                                            this.debug("insertAdsense : No Fallback found, remove element (" + target + ")");
                                            mainContainer = this.up(node, "adsenseContainer");
                                            if (mainContainer){
                                                found = false;
                                                //Existiert im Container Werbung ?
                                                if (/(adsense([0-9]+))\">(.*){1,}[^\s]<\/div>/.test(mainContainer.innerHTML.toLowerCase()) == true) {
                                                    this.debug("insertAdsense : Remove only Element");
                                                    node.parentNode.removeChild(node);
                                                }else{
                                                    this.debug("insertAdsense : Remove complete container");
                                                    mainContainer.parentNode.removeChild(mainContainer);
                                                }
                                            }else{
                                                this.debug("insertAdsense : Cant remove element, doesnt find the main class adsenseContainer");
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }                    
            }

            for (var i = 0; i < ads.noAds.element.length; i++){
                noAd = ads.noAds.element[i];
                eval("part = ads.options.part" + (noAd.callcount + 1) + " || false;"); 
                if (part != false){
                    this.debug("insertAdsense : Missing " + noAd.missing + " adsense for Part" + (noAd.callcount));
                    if ( (part.fallback_keyword) && (ads.options.allow_fallback == true) ){
                        this.debug("insertAdsense : Using fallback keyword " + part.fallback_keyword);
        
                        ads.callcount = 0;
                        part.keyword = part.fallback_keyword;
                        part.fallback_keyword = "";
                        part.fallback = true;
                        part.howmany = noAd.missing;
                        singleAdRequest = noAd.missing;
                        ads.futureCalls.push(part);
                        if (blockedAdsense == false) this.getNextAdsense();
                    }else{
                        for (var y=0; y < noAd.targets.length; y++){
                            target = noAd.targets[y];
                            for (var x = 0; x < part.container.length; x++){
                                element = part.container[x];
                                for (var singleTarget in element){
                                    if (singleTarget == target){


                                        fallback_html = eval("part.container[x]." + target + ".fallback_html");
                                        node = document.getElementById(target);
                                        if (fallback_html){
                                            this.debug("insertAdsense : Using fallback HTML for " + " + target + ");
                                            node.innerHTML = fallback_html;
                                        }else{


                                            mainContainer = this.up(node, "adsenseContainer");
                                            if (mainContainer){
                                                this.debug("insertAdsense : No Fallback found, remove element (" + target + ")");
                                                found = false;
                                                //Existiert im Container Werbung ?
                                                if (/(adsense([0-9]+))\">(.*){1,}[^\s]<\/div>/.test(mainContainer.innerHTML.toLowerCase()) == true) {
                                                    this.debug("insertAdsense : Remove only Element");
                                                    node.parentNode.removeChild(node);
                                                }else{
                                                    this.debug("insertAdsense : Remove complete container");
                                                    mainContainer.parentNode.removeChild(mainContainer);
                                                }
                                            }else{
                                                this.debug("insertAdsense : Cant remove element, doesnt find the main class adsenseContainer");
                                            }




                                        }


                                    }
                                }
                            }
                        }

                    }
                }
            }
        }
    }


    //Wird bei verwendung von document.write aufgerufen (after dom ready!)
    this.document_write_overload = function(param){
        quelle = false;
        useddoc = this.getDocumentHandler();

        this.debug("document_write_overload : Recive Code : ");
        this.debug(param);

        if (camaoIndexOf(param,"google_ad_output") !== -1){
            parts_tmp1 = param.split("<script");
            jscode = parts_tmp1[0];
            eval(jscode);

            parts_tmp1 = param.split("src=\"");
            parts_tmp2 = parts_tmp1[1].split("\"");
            quelle = parts_tmp2[0];

        }else if (camaoIndexOf(param,"googlesyndication.com")  !== -1){
            parts_tmp1 = param.split("src=\"");
            parts_tmp2 = parts_tmp1[1].split("\"");
            quelle = parts_tmp2[0];

        }else if (camaoIndexOf(param,"google_protectAndRun")  !== -1){
            parts_tmp1 = param.split("<script>");
            parts_tmp2 = parts_tmp1[1].split("</");
            jscode = parts_tmp2[0];
            eval(jscode);

        }else if (camaoIndexOf(param,"googleads.g.doubleclick.net")  !== -1){
            parts_tmp1 = param.split("src=\"");
            parts_tmp2 = parts_tmp1[1].split("\"");
            quelle = parts_tmp2[0];

        }else if (camaoIndexOf(param,"www.google.com")  !== -1){
            parts_tmp1 = param.split("src=\"");
            parts_tmp2 = parts_tmp1[1].split("\"");
            quelle = parts_tmp2[0];

        }else{
            this.debug("document_write_overload : Unknown string recived : " + param);
        }

        if (quelle != false){
            //Aus irgendeinem grund wird der letzte call doppelt abgesetzt
            if (quelle != settings.lastdoubleclicksurl){
                settings.lastdoubleclicksurl = quelle;
                var jslink = document.createElement("script");
                jslink.setAttribute("type", "text/javascript");
                jslink.setAttribute("src", quelle);
                useddoc.appendChild(jslink)
            }
        }
    }
    
    //Liefert die Anzahl der Zonen
    this.countParts = function() {
        found = 0;
        for(var i = 0; i < 10; i++){
            eval("part = ads.options.part" + (i + 1) + " || false;"); //(recived.callcount + 1) weil unsere Parts bei 1 anfangen nicht bei 0
            if (part != false) found++;
        }
        return found;
    }

    this.getTemplateIDByPart = function(part){
        eval("part = ads.options.part" + (part + 1 )+ " || false;"); //(recived.callcount + 1) weil unsere Parts bei 1 anfangen nicht bei 0
        if (part != false){
            return part.template;
        }
    }

    //Liefert anhand von
    this.createAdsenseContext = function(target, ad, templateNumber){

        this.debug("createAdsenseContext : Inserting Ads for Target : " + target.id);

        if (ad.type != "image"){
            usedTemplate = document.getElementById("adsense_template_" + templateNumber);
        }else{
            usedTemplate = document.getElementById("adsense_template_9");
        }


        if (usedTemplate){
            cloned = usedTemplate.cloneNode(true);
            cloned.id = "";
            for (var x = 0; x < 15; x++){ ad.url = ad.url.replace("&amp;","&"); }

                if (ad.type == "image"){
                    this.select(cloned, "adsense-image_url")[0].src = ad.image_url;
                    this.select(cloned, "adsense-image_url")[0].width = ad.image_width;
                    this.select(cloned, "adsense-image_url")[0].height = ad.image_height;
                    this.select(cloned, "adsense-url")[0].href = ad.url;
                    this.select(cloned, "adsense-url")[0].target = "_blank";

                }else{
                    this.select(cloned, "adsense-visible_url")[0].innerHTML = ad.line1;
                    this.select(cloned, "adsense-url")[0].href = ad.url;
                    this.select(cloned, "adsense-url")[0].target = "_blank";
                    this.select(cloned, "adsense-line2")[0].innerHTML = ad.line2;
                    this.select(cloned, "adsense-line3")[0].innerHTML = ad.line3 || "";
                    this.select(cloned, "adsense-visible_url")[1].innerHTML = ad.visible_url;
                    this.select(cloned, "adsense-url2")[0].href = ad.url;
                    this.select(cloned, "adsense-url2")[0].target = "_blank";
                }    
                target.appendChild(cloned);
                cloned.onmouseover = function(){
                this.className = this.className.replace(" " + settings.hoverclass,"");
                this.className = this.className + " " + settings.hoverclass;
            }
    
            cloned.onmouseout = function(){ this.className = this.className.replace(" " + settings.hoverclass,""); }
            cloned.style.display = "";

        }else{
            this.debug("createAdsenseContext : Template not found, try to load 'adsense_template_" + templateNumber + "'");
        }
    }
    
    //Liefert das Template anhand der ID aus
    this.getTemplate = function(part){
        try{
            if ( (settings.usedTemplatesPartType[part] == "afc") || (settings.usedTemplatesPartType[part] == "afc_image") ){
                feedbackurl = google_info.feedback_url;
            }else{
                feedbackurl = "http://services.google.com/feedback/online_hws_feedback";
            }

        }catch(e){
            this.debug("createAdsenseContext : Feedback nicht gefunden! ");
            feedbackurl = "http://services.google.com/feedback/online_hws_feedback";
        }

        if (ads.options.language == "hu"){
            google_words = "Google-hirdet&eacute;sek";
        }else if (ads.options.language == "ro"){
            google_words = "Anunturi Google";
        }else if (ads.options.language == "pt"){
            google_words = "An&uacute;ncios do Google";
        }else if (ads.options.language == "en"){
            google_words = "Ads by Google";
        }else if (ads.options.language == "nl"){
            google_words = "Google de aankondiging";
        }else if (ads.options.language == "it"){
            google_words = "Annuncio da Google";
        }else if (ads.options.language == "es"){
            google_words = "Anuncios Google";
        }else if (ads.options.language == "fr"){
            google_words = "Annonces Google";
        }else if (ads.options.language == "se"){
            google_words = "Google-annonser";
        }else if (ads.options.language == "no"){
            google_words = "Google De besked";
        }else if (ads.options.language == "fi"){
            google_words = "Google Ilmoitus";
        }else if (ads.options.language == "dk"){
            google_words = "Google Meddelelsen";
        }else if (ads.options.language == "pl"){
            google_words = "Reklamy Google";
        }else if (ads.options.language == "hr"){
            google_words = "Google oglasi";
        }else if (ads.options.language == "tr"){
            google_words = "Google Reklamları";
        }else if (ads.options.language == "gr"){
            google_words = "Ads by Google";
        }else if (ads.options.language == "ru"){
            google_words = "Ads by Google";
        }else{
            google_words = "Google-Anzeigen";
        }

        if (part == 1){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_1' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<div class='adsenseItem'>" +
                            "<a href='#' class='adsense-url'>" +
                                "<span class='adsense-visible_url'></span>" +
                            "</a>" +
                            "<a class='adsense-url2'>" +
                                " - <span class='adsense-visible_url'></span>" +
                            "</a>" +
                            "<div class='adsense-lines'>" +
                                "<span class='adsense-line2'></span>" +
                                "<span class='adsense-line3'></span>" +
                            "</div>" +
                        "</div>" +
                    "</div>" +
                "</div>";
        
        }else if (part == 2){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_2' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<div class='adsenseItem'>" +
                        "<a href='#' class='adsense-url name'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "<span class='adsense-line2'></span>" +
                        "<span class='adsense-line3'></span>" +
                        "<br />"+
                        "<a class='adsense-url2'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "</div>" +
                    "</div>" +
                "</div>";
    
        }else if (part == 3){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_3' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<div class='adsenseItem'>" +
                            "<a href='#' class='adsense-url'>" +
                                "<span class='adsense-visible_url'></span>" +
                            "</a>" +
                            "<a class='adsense-url2'>" +
                                "<span class='adsense-visible_url'></span>" +
                            "</a>" +
                            "<div class='adsense-lines'>" +
                                "<span class='adsense-line2'></span>" +
                                "<span class='adsense-line3'></span>" +
                            "</div>" +
                            "<a class='adsense-url3'>" +
                                "<span class='adsense-visible_url'></span>" +
                            "</a>" +
                        "</div>" +
                    "</div>" +
                "</div>";
        }else if (part == 4){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_4' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<div class='adsenseItem'>" +
                        "<a href='#' class='adsense-url name'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "<span class='adsense-line2'></span>" +
                        "<span class='adsense-line3'></span>" +
                        "<a class='adsense-url2'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "</div>" +
                    "</div>" +
                "</div>";
        }else if (part == 5){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_5' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<div class='adsenseItem'>" +
                            "<a href='#' class='adsense-url'>" +
                                "<span class='adsense-visible_url'></span>" +
                            "</a>" +
                            "<br/>"+
                            "<a class='adsense-url2'>" +
                                " - <span class='adsense-visible_url'></span>" +
                            "</a>" +
                            "<div class='adsense-lines'>" +
                                "<span class='adsense-line2'></span>" +
                                "<span class='adsense-line3'></span>" +
                            "</div>" +
                        "</div>" +
                    "</div>" +
                "</div>";
                
        }else if (part == 6){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_6' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<div class='adsenseItem'>" +
                        "<a href='#' class='adsense-url name'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "<br />"+
                        "<span class='adsense-line2'></span>" +
                        "<span class='adsense-line3'></span>" +
                        "<br />"+
                        "<a class='adsense-url2'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "</div>" +
                    "</div>" +
                "</div>";
        }else if (part == 7){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_7' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<div class='adsenseItem'>" +
                        "<a href='#' class='adsense-url name'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "<br />"+
                        "<span class='adsense-line2'></span>" +
                        "<span class='adsense-line3'></span>" +
                        "<a class='adsense-url2'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "</div>" +
                    "</div>" +
                "</div>";
        }else if (part == 8){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_8' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<div class='adsenseItem'>" +
                        "<a href='#' class='adsense-url name'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "<br />"+
                        "<div class='adsense-lines'>" +
                            "<span class='adsense-line2'></span>" +
                            "<span class='adsense-line3'></span>" +
                        "</div>" +
                        "<br />"+
                        "<a class='adsense-url2'>" +
                            "<span class='adsense-visible_url'></span>" +
                        "</a>" +
                        "</div>" +
                    "</div>" +
                "</div>";

        //Dieses Template ist NUR für Images!!
        }else if (part == 9){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_9' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<a href='' class='adsense-url'>" + 
                            "<img src='' class='adsense-image_url'>" + 
                        "</a>" + 
                    "</div>" +
                "</div>";
        }else if (part == 10){
            return "" +
                "<div>" +
                    "<div class='adsense' id='adsense_template_10' style='display:none;'>" +
                        "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                        "<div class='adsenseItem'>" +
                            "<a href='#' class='adsense-url'>" +
                                "<span class='adsense-visible_url'></span>" +
                            "</a>" +
                            "<br/>"+
                            "<a class='adsense-url2'>" +
                                "<span class='adsense-visible_url'></span>" +
                            "</a>" +
                            "<div class='adsense-lines'>" +
                                "<span class='adsense-line2'></span>" +
                                "<span class='adsense-line3'></span>" +
                            "</div>" +
                        "</div>" +
                    "</div>" +
                "</div>";
        }else if (part == 11){
            return "" +
            "<div>" +
                "<div class='adsense' id='adsense_template_11' style='display:none;'>" +
                    "<span class='adsense-googleAds'><a href='" + feedbackurl + "' target='_blank'>" + google_words + "</a></span>" +
                    "<div class='adsenseItem'>" +
                    "<a href='#' class='adsense-url name'>" +
                        "<span class='adsense-visible_url'></span>" +
                    "</a>" +
                    "<br />"+
                    "<a class='adsense-url2'>" +
                    "<span class='adsense-visible_url'></span>" +
                    "</a>" +
                    "<span class='adsense-line2'></span>" +
                    "<span class='adsense-line3'></span>" +
                    "</div>" +
                "</div>" +
            "</div>";
        }
        
    }

    //Helper Functions
    this.getDocumentHandler = function(){ return document.body || document.documentElement; }
    this.$ = function(id){ return document.getElementById(id); }
    this.select = function(element, str){
        var Rx= RegExp('\\b'+str+'\\b');
        var who, i= 0, A= [], tem, temp;
        var G= element.getElementsByTagName('*');
        while(G[i]){
            tem= G[i++];
            temp=tem.className|| '';
            if(Rx.test(temp)) A.push(tem);
        }
        return A;
    }
    this.up = function(element, classname){
        if (element){
            if (camaoIndexOf(element.className,classname) != -1){
                return element;
            }else{
                stop = false;
                do{
                    if (!element.parentNode){
                        return false;
                    }else{
                        element = element.parentNode;
                        if (camaoIndexOf(element.className,classname) != -1){
                           return element;
                        }
                    
                    }
                } while(stop == false);
            }
        }else{
            return false;
        }
    }

    this.debug = function(msg){
        if (ads.options.debug){ 
            console.log(msg);
        }else{
            errorLog = errorLog + "\n" + msg;
        }
    }

    this.getErrorLog = function(){ return errorLog; }

}

function camaoIndexOf(obj,ele){
    if (typeof obj == "undefined") return -1;
    for(var i=0; i<ele.length; i++){ if(ele[i]==obj) return i; }
    return -1;
}
//Falls wir im IE sind dann kennt er indexOF nicht, also nachbaun ;)
/*if(!Array.indexOf){
    Array.prototype.indexOf = function(obj){
        for(var i=0; i<this.length; i++){ if(this[i]==obj) return i; }
        return -1;
    }
}*/

//Wird von Google aufgerufen, liefert ein array mit werbung
function google_ad_request_done (google_ads) { camaoAdsenseObj.reciveAdsense(google_ads); camaoAdsenseObj.getNextAdsense(); }
function google_afs_request_done(google_ads) { camaoAdsenseObj.reciveAdsense(google_ads); camaoAdsenseObj.getNextAdsense(); }

//Wir initialisieren unsere klasse
var camaoAdsenseObj = new camaoAdsense();