/*
 *	Fire up the jQuery sortable and draggable
 */

(function ($) {
  "use strict";

  $.ZnHtml = function () {
    // Here we can set some global variables if needed
    this.scope =
      $(".zn_pb_wrapper").length > 0 ? $(".zn_pb_wrapper") : $(document);

    //activate the plugin
    this.zinit();
    // This is needed for the data conversion
    this.zn_dummy_step = 0;
    this.failed = 0;
  };

  $.ZnHtml.prototype = {
    zinit: function () {
      var fw = this,
        file_uploader = "";

      fw.addactions();
      fw.refresh_events();
    },

    refresh_events: function (content) {
      var fw = this;

      //Refresh modal
      fw.launch_modal(content);
      fw.enable_footer_widget_layouts(content);
      fw.launch_ui_slider(content);
      fw.launch_color_picker(content);
      fw.launch_ui_buttons(content);
      fw.add_el(content);
      fw.remove_el(content);
      fw.clone_el(content);
      fw.icon_list(content);
      fw.make_sortable(content);
      fw.dependencies(content);
      fw.timepicker(content);
      fw.datepicker(content);
      fw.dragKeyFields(content);
      fw.ace_editor(content);
      fw.boxmodel(content);
      fw.tabbed_group(content);
      fw.date_format(content);
      fw.radio_image(content);
      fw.smart_select(content);

      // enable copytoclipboard
      fw.copyToClipboard(content);

      fw.enable_wpLink(content);
    },

    addactions: function () {
      var fw = this;

      fw.scope.on("ZnNewFWContent", function (e) {
        fw.refresh_events(e.content);
      });

      // USING THE WP TRIGGERS
      $(document).on("widget-updated widget-added", function (data, el) {
        fw.refresh_events($(el));
      });

      // Icon font functionality
      fw.delete_icon_font();
      fw.download_icon_font();
      fw.upload_icon_font();

      fw.add_g_font();

      // ENABLE Theme updater
      fw.theme_updater();
      fw.zn_refresh_pb();
    },

    tabbed_group: function (scope) {
      var fw = this,
        element = scope
          ? scope.find(".znopt_tabbed_menu li a")
          : $(".znopt_tabbed_menu li a");
      element.on("click", function (e) {
        e.preventDefault();

        var container = $(this).closest(".znopt_tabbed_group"),
          menu = container.find(".znopt_tabbed_menu li"),
          tabs = container.find(".znopt_single_tab");

        menu.removeClass("active");
        tabs.removeClass("active");
        $(this).parent().addClass("active");
        $($(this).attr("href")).addClass("active");
      });
    },

    enable_wpLink: function (scope) {
      var element = scope
        ? scope.find(".zn_internal_button_trigger")
        : $(".zn_internal_button_trigger");

      element.on("click", function (e) {
        e.preventDefault();

        var container = $(this).closest(".zn_option_content"),
          // fields
          url_value_container = container.find(".zn-form--url"),
          target_value_container = container.find(".zn-form--url-target"),
          title_value_container = container.find(".zn-form--url-title"),
          // wpLink fields
          wpLinkUrl = $("#wp-link-url"),
          wpLinkTarget = $("#wp-link-target"),
          wpLinkText = $("#wp-link-text");

        wpLink.setDefaultValues = function () {
          wpLinkUrl.val(url_value_container.val());

          if (target_value_container.val() == "_blank") {
            wpLinkTarget.attr("checked", "checked").trigger("change");
          } else {
            wpLinkTarget.removeAttr("checked").trigger("change");
          }
        };

        wpLink.open(false, false, title_value_container.val());

        $("#wp-link-submit")
          .off("click")
          .on("click", function (e) {
            e.preventDefault();
            // Add URL
            var url = wpLinkUrl.val();
            url_value_container.val(url);
            // Add target
            var target = wpLinkTarget;
            if (target.is(":checked")) {
              target_value_container.val("_blank");
            }
            // Add Title / text
            var linkText = wpLinkText.val();
            title_value_container.val(linkText);

            wpLink.close();
          });
      });
    },

    date_format: function (scope) {
      var fw = this,
        element = scope
          ? scope.find(".zn_date_format_input")
          : $(".zn_date_format_input");

      element.on("change", function () {
        var format = $(this);
        format.siblings(".spinner").addClass("is-active");
        $.post(
          ajaxurl,
          {
            action: "date_format",
            date: format.val(),
          },
          function (d) {
            format.siblings(".spinner").removeClass("is-active");
            format.siblings(".example").text(d);
          }
        );
      });
    },

    radio_image: function (scope) {
      var element = scope
        ? scope.find(".zn-radio-image-container")
        : $(".zn-radio-image-container");

      if (!element.length) {
        return false;
      }

      element.each(function (index, el) {
        var $el = $(el);

        var btn = $el.find(".zn-radio-button:not([data-dummy])"),
          select = $el.find(".zn-radio-image-select");

        btn.on("click", function (event) {
          event.preventDefault();
          btn.removeClass("active");
          btn.parent().removeClass("active");

          var $this = $(this),
            val = $this.attr("data-value");

          $this.addClass("active");
          $this.parent().addClass("active");
          select.val(val).change();
        });
      });
    },

    smart_select: function (scope) {
      var element = scope
        ? scope.find(".zn-smartselect")
        : $(".zn-smartselect");

      if (!element.length) {
        return false;
      }

      element.each(function (index, el) {
        var $el = $(el),
          btn = $el.find(".zn-smartselect-label"),
          items = $el.find(".zn-smartselect-item"),
          select = $el.find(".zn-smartselect-selectlist"),
          $modal = $el.closest(".zn-modal-form");

        btn.on("click", function (event) {
          event.preventDefault();
          $el.toggleClass("is-opened");

          $modal.css(
            "min-height",
            $el.find(".zn-smartselect-dropdown").height() + 120
          );
        });

        items.hover(function (event) {
          $el
            .find(".zn-smartselect-hoverImg img")
            .attr("src", $(this).attr("data-img"));
        });

        items.on("click", function (event) {
          event.preventDefault();

          var $this = $(this),
            val = $this.attr("data-value"),
            label = $this.find(".zn-smartselect-item-title").text();

          items.removeClass("is-active");
          $this.addClass("is-active");

          // close dropdown
          $el.removeClass("is-opened");
          // change list's value
          select.val(val).change();
          // change label's value
          btn.text(label);

          $modal.css("min-height", "");
        });

        $(document).on("click", function (e) {
          if ($el.hasClass("is-opened")) {
            $el.removeClass("is-opened");
          }
        });

        $el.on("click", function (event) {
          event.stopPropagation();
        });
      });
    },

    // Enable footer widgets option
    enable_footer_widget_layouts: function (scope) {
      var fw = this,
        element = scope ? scope.find(".zn_mp") : $(".zn_mp"),
        widget_columns = scope
          ? scope.find(".zn_mp .zn_nop ul li")
          : $(".zn_mp .zn_nop ul li"),
        widget_columns_styles = scope
          ? scope.find(".zn_mp .zn_position_var_options ul li")
          : $(".zn_mp .zn_position_var_options ul li");

      if (!element.length) {
        return false;
      }

      /* Columns numbers */
      widget_columns.on("click", function (e) {
        e.preventDefault();

        var val = $(this).html(),
          container = $(this).closest(".zn_mp"),
          json = container.find(".zn_all_options").html(),
          all_styles = $.parseJSON(json),
          divs = container.find(".zn_positions_display"),
          new_value = {},
          i;

        /* Add active class to current option*/
        $(this).closest(".zn_nop").children("input").attr("value", val);
        /* ADD ATTRIBUTE FOR NUMBER OF COLUMNS*/
        container
          .find(".zn_positions .zn_widgets_positions")
          .attr("data-columns", val);
        new_value[val] = [all_styles[val][0]];
        /* UPDATE INPUT VALUE BASED ON SELECTION*/
        container
          .find(".zn_positions .zn_widgets_positions")
          .attr("value", JSON.stringify(new_value));
        $(this).closest(".zn_nop").find("li").removeClass("active");
        $(this).addClass("active");
        /* Hide the extra divs*/
        divs.children().removeClass("hidden");
        divs.children().slice(val).addClass("hidden");
        for (i = 0; i < all_styles[val][0].length; i++) {
          container
            .find(".zn_position:nth-child(" + (i + 1) + ")")
            .attr("class", "zn_position zn-grid-" + all_styles[val][0][i] + "");
        }

        /* Show the proper styles*/
        container.find(".zn_position_var_options .zn_number_list").html("");

        for (i = 0; i < all_styles[val].length; i++) {
          var css = "";
          if (i === 0) {
            css = 'class="active"';
          }
          container
            .find(".zn_position_var_options .zn_number_list")
            .append("<li " + css + ">" + (i + 1) + "</li>");
        }
      });

      /* Columns styles */
      element.on("click", ".zn_position_var_options ul li", function (e) {
        e.preventDefault();

        var val = $(this).html() /* GET SELECTED MODULE VARIATION*/,
          container = $(this).closest(".zn_mp"),
          divs = container.find(
            ".zn_positions_display"
          ) /* get option top parent*/,
          all_val = container
            .find(".zn_positions .zn_widgets_positions")
            .attr("data-columns") /* GET THE SELECTED NUMBER OF COLUMNS*/,
          json = container
            .find(".zn_all_options")
            .html() /* GET ALL POSSIBLE COMBINATIONS*/,
          all_styles = $.parseJSON(json),
          new_value = {};
        /* CREATE NEW JSON ARRAY TO POPULATE THE INPUT*/

        /* UPDATE THE INPUT WITH SELECTED COMBINATION*/
        new_value[all_val] = [all_styles[all_val][val - 1]];

        $(this)
          .closest(".zn_positions")
          .children("input")
          .val(JSON.stringify(new_value));
        $(this).closest(".zn_number_list").find("li").removeClass("active");
        $(this).addClass("active");
        /* Hide the extra divs*/
        divs.children().removeClass("hidden");
        divs.children().slice(all_val).addClass("hidden");
        for (var i = 0; i < all_styles[all_val][val - 1].length; i++) {
          container
            .find(".zn_position:nth-child(" + (i + 1) + ")")
            .attr(
              "class",
              "zn_position zn-grid-" + all_styles[all_val][val - 1][i] + ""
            );
        }
      });
    },

    zn_refresh_pb: function () {
      var fw = this;
      /* Add a new element for theme options */
      $(".zn_refresh_pb_btn").on("click", function (e) {
        var el = $(this);

        if (el.hasClass("zn_blocked_btn")) {
          return false;
        }

        // SHOW THE MESSAGE

        el.addClass("zn_blocked_btn");

        var data = {
          action: "znhgkl_refresh_pb_data",
          zn_ajax_nonce: ZnAjax.security,
        };

        jQuery.post(ajaxurl, data, function (response) {
          new $.ZnModalMessage("Page builder data refreshed");
          el.removeClass("zn_blocked_btn");
        });

        e.preventDefault();
      });
    },

    theme_updater: function () {
      var fw = this;
      /* Add a new element for theme options */
      $(".zn_run_theme_updater").on("click", function (e) {
        e.preventDefault();
        var el = $(this);

        if (el.hasClass("zn_blocked_btn")) {
          return false;
        }

        // SHOW THE MESSAGE
        new $.ZnModalConfirm(
          "We strongly recommend making a full theme backup ? Please note that data loss may occur. Are you sure you want to continue ?",
          "Cancel",
          "Perform theme update",
          function () {
            el.addClass("zn_blocked_btn");

            var data = {
              step: fw.zn_dummy_step,
              data: false,
              action: "znhgkl_process_theme_updater",
              zn_ajax_nonce: ZnAjax.security,
            };

            fw.process_theme_updater(data, function () {
              el.removeClass("zn_blocked_btn");
            });
          }
        );
      });
    },

    process_theme_updater: function (data, callback) {
      var fw = this,
        message_container = $(".zn_updater_msg_container");
      jQuery
        .post(
          ajaxurl,
          data,
          function (response, textStatus, jqXHR) {
            if (
              textStatus.status == "500" ||
              typeof response === "undefined" ||
              !response
            ) {
              setTimeout(function () {
                message_container.append(
                  "<div>Something went wrong... will retry the last convert</div>"
                );
                fw.process_theme_updater(data, callback);
              }, 3000);
              return false;
            }

            // GET ONLY THE AJAX RESPONSE
            var source = $("<div>" + response + "</div>");
            response = source.find(".zn_json_response").html();
            response = $.parseJSON(response);

            if (response.status == "ok") {
              if (response.response_text.length > 0) {
                message_container.append(
                  "<div>" + response.response_text + "</div>"
                );
              }

              data.data = {};
              data.step = response.step;
              if (typeof response.data != "undefined") {
                data.data = response.data;
              }
              fw.process_theme_updater(data, callback);
            } else if (response.status == "done") {
              if (response.response_text.length > 0) {
                message_container.append(
                  "<div>" + response.response_text + "</div>"
                );
              }
              callback();
              new $.ZnModalMessage("All done !");
            } else {
              fw.zn_dummy_step = 0;
            }
            //console.log(response);
          },
          "html"
        )
        .fail(function () {
          setTimeout(function () {
            message_container.append(
              "<div>Something went wrong... will retry the last convert</div>"
            );
            fw.process_theme_updater(data, callback);
          }, 3000);
        });
    },

    enable_tinymce: function (scope) {
      if (typeof tinymce === "undefined") {
        return;
      }

      var elements = scope
        ? scope.find(".zn_tinymce").not(".zn_group .zn_tinymce")
        : $(".zn_tinymce").not(".zn_group .zn_tinymce");
      var length = elements.length;

      if (length > 0) {
        for (var i = 0; i < length; i++) {
          var id = elements[i].id,
            object = $(elements[i]);

          // Init Quicktag
          if (_.isUndefined(tinyMCEPreInit.qtInit[id])) {
            window.tinyMCEPreInit.qtInit[id] = _.extend(
              {},
              window.tinyMCEPreInit.qtInit[wpActiveEditor],
              { id: id }
            );
            quicktags(tinyMCEPreInit.qtInit[id]);
          }

          // Init tinymce
          if (
            window.tinyMCEPreInit &&
            window.tinyMCEPreInit.mceInit.zn_dummy_editor_id
          ) {
            // Get an instance of tinyMCE init config
            window.tinyMCEPreInit.mceInit[id] = _.extend(
              _.clone(window.tinyMCEPreInit.mceInit.zn_dummy_editor_id),
              {
                id: id,
                selector: "#" + id,
              }
            );

            window.tinyMCE.execCommand("mceRemoveEditor", true, id);
            tinymce.init(window.tinyMCEPreInit.mceInit[id]);
            window.wpActiveEditor = id;
          }
        }
      }
    },

    // Launch modals
    launch_modal: function (scope) {
      var fw = this,
        element = scope
          ? scope.find(".zn_modal_trigger")
          : $(".zn_modal_trigger");

      element.znmodal();
    },

    timepicker: function (scope) {
      var element = scope
        ? scope.find(".zn_time_picker")
        : $(".zn_time_picker");

      element.timepicker({
        timeFormat: "H:i",
      });
    },

    datepicker: function (scope) {
      var element = scope
        ? scope.find(".zn_date_picker")
        : $(".zn_date_picker");

      element
        .datepicker({
          dateFormat: "yy-mm-dd",
        })
        .datepicker("widget")
        .wrap('<div class="ll-skin-nigran"/>');
    },

    boxmodel: function (scope) {
      var element = scope
        ? scope.find(".js-boxmodel-field")
        : $(".js-boxmodel-field");

      element.each(function (index, el) {
        var linked = $(el).find(".zn-boxmodel-linked"),
          fields = $(el).find(".zn_input[type=text]");

        // sync fields when linked
        fields.dragKeyField();

        fields.on("change", function (e) {
          var currTarget = $(e.currentTarget),
            currTargetVal =
              currTarget.val() !== "" ? currTarget.val().trim() : "0px";

          if (linked.is(":checked")) {
            fields.each(function (index, el) {
              $(el).not('[disabled="disabled"]').val(currTargetVal);
            });
          }
        });

        // sync fields when linked is changed (and sync with the first one)
        linked.on("change", function (event) {
          if ($(this).is(":checked")) {
            fields.each(function (index, el) {
              $(el)
                .not('[disabled="disabled"]')
                .val($(fields.first()).val().trim());
            });
          }
        });
      });
    },

    dragKeyFields: function (scope) {
      var field = scope
        ? scope.find(".js-dragkeyfield")
        : $(".js-dragkeyfield");

      field.each(function (index, el) {
        var $el = $(el),
          $opt = {};

        $opt.hasUnit = $el.is("[data-no-unit]") ? false : true;
        $opt.unit =
          $opt.hasUnit && $el.attr("data-dragkey-unit") !== ""
            ? $el.attr("data-dragkey-unit")
            : "px";

        if (
          ($el.is("[data-dragkey-min]") &&
            $el.attr("data-dragkey-min") !== "") ||
          ($el.is("[min]") && $el.attr("min") !== "")
        )
          $opt.min = $el.attr("data-dragkey-min");

        if (
          ($el.is("[data-dragkey-max]") &&
            $el.attr("data-dragkey-max") !== "") ||
          ($el.is("[max]") && $el.attr("max") !== "")
        )
          $opt.max = $el.attr("data-dragkey-max");

        $el.dragKeyField($opt);
      });
    },

    ace_editor: function (scope) {
      var element = scope ? scope.find(".zn_code_input") : $(".zn_code_input");
      element.each(function () {
        var editor_element = $(this),
          editor = ace.edit(editor_element.attr("id")),
          editor_type = $(this).data("editor_type");
        editor.setTheme("ace/theme/chrome");
        editor.getSession().setMode("ace/mode/" + editor_type);
        editor.getSession().setUseWrapMode(true);
        editor.setOptions({
          maxLines: Infinity,
        });
        editor.on("change", function () {
          editor_element.next("textarea").val(editor.getValue());
        });
      });
    },

    // jQuery UI slider
    launch_ui_slider: function (scope) {
      var fw = this,
        element = scope
          ? scope.find(".slider-range-max")
          : $(".slider-range-max");

      // Activate jQuery UI slider
      $(element).each(function () {
        var $el = $(this),
          $min = parseFloat($el.attr("data-min")),
          $max = parseFloat($el.attr("data-max")),
          step = parseFloat($el.attr("data-step")) || 1,
          disabled = $el.is('[data-disabled="true"]') ? true : false,
          $slider_input = $el.siblings(".wp-slider-input");

        $el.slider({
          range: "max",
          disabled: disabled,
          min: $min,
          max: $max,
          value: parseFloat($el.attr("data-value")) || $min,
          step: step,
          slide: function (event, ui) {
            $slider_input.val(ui.value).trigger("change");
          },
        });

        $slider_input.on("change", function () {
          var $this = $(this),
            $elInputVal =
              isNaN($this.val()) || $this.val() === "" ? 0 : $this.val();

          if (parseFloat($elInputVal) < $min) {
            $this.val($min);
          }
          if (parseFloat($elInputVal) > $max) {
            $this.val($max);
          }

          // CHECK IF THE INPUT IS NOT A NUMBER
          if (
            (isNaN($elInputVal) && $elInputVal != "auto") ||
            $elInputVal === ""
          ) {
            $this.val($min);
          }

          if ($elInputVal == "auto") {
            $el.slider("value", 0);
          } else {
            $el.slider("value", parseFloat($elInputVal));
          }
        });
      });
    },

    // WP Color Picker
    launch_color_picker: function (scope) {
      var fw = this,
        element = scope ? scope.find(".zn_colorpicker") : $(".zn_colorpicker");

      element.each(function (el) {
        var colors =
          typeof zn_color_palette != "undefined"
            ? zn_color_palette
            : '["#000","#fff","#d33","#d93","#ee2","#81d742","#1e73be","#8224e3"]';

        var input = $(this);

        // RE-CREATE THE COLORPICKER ON CLONE
        if ($(this).hasClass("wp-color-picker")) {
          var container = $(this).closest(".input-append");

          input = container.find("input.zn_colorpicker");

          container.html(input);
        }

        input.wpColorPicker({
          change: function (event, ui) {
            // TRIGGER A SPECIAL EVENT FOR THE LIVE CHANGE
            $(this).trigger("zn_change");
          },
          palettes: colors,
        });
      });
    },

    // jQuery UI buttons
    launch_ui_buttons: function (scope) {
      var fw = this,
        element = scope ? scope.find(".zn_buttons") : $(".zn_buttons");

      // Activate the buttons
      $(element).button();
    },

    // Launch icon list
    icon_list: function (scope) {
      var fw = this,
        element = scope
          ? scope.find(".zn_icon_container span")
          : $(".zn_icon_container span");
      $(element).on("click", function () {
        var icon = jQuery(this).attr("data-unicode"),
          family = jQuery(this).attr("data-zniconfam"),
          opts_container = jQuery(this).closest(".zn_icon_op_container");

        if ($(this).hasClass("zicon_active")) {
          // CLEAR THE FIELDS
          opts_container.find(".zn_icon_family").val("").trigger("change");
          opts_container.find(".zn_icon_unicode").val("").trigger("change");

          $(this).removeClass("zicon_active");
        } else {
          opts_container.find(".zn_icon_family").val(family).trigger("change");
          opts_container.find(".zn_icon_unicode").val(icon).trigger("change");

          //opts_container.find('input').val(icon).trigger('change');
          opts_container
            .closest(".zn_icon_op_container")
            .find(".zicon_active")
            .removeClass("zicon_active");
          jQuery(this).addClass("zicon_active");
        }
      });

      $(element).on(
        "hover",
        function (e) {
          var position = $(this).offset(),
            left = position.left + $(this).width() / 2,
            top = position.top;

          if ($(".znIconHolder").length === 0) {
            $("body").append('<div class="znIconHolder"></div>');
          }

          $(".znIconHolder")
            .show()
            .css({ left: left, top: top })
            .html($(this).clone());
        },
        function () {
          $(".znIconHolder").hide().html("");
        }
      );
    },

    // Add new element button
    add_el: function (scope) {
      var fw = this,
        element = scope ? scope.find(".zn_add_button") : $(".zn_add_button");

      /* Add a new element for theme options */
      $(element).on("click", function (e) {
        e.preventDefault();

        // GET THE ELEMENT TO BE ADDED
        var el = $(this),
          $container = el.prev(),
          max_items = el.attr("data-max_items");

        var JSONdata = el.parent().find(".znhgfw-repeater-config").text();

        if ($container.hasClass("zn_add_button_inactive")) {
          return false;
        }

        // Don't allow the user to spam the add button
        $container.addClass("zn_add_button_inactive");

        var data = {
          option_schema: JSONdata.trim(),
          action: "znhgfw_html_group_add",
          zn_ajax_nonce: ZnAjax.security,
        };

        jQuery.post(ajaxurl, data, function (response) {
          if (response.success) {
            var new_content = $(response.data.html_markup);

            $container.append(new_content).zn_sortable_order();

            // Create an event for new content received
            fw.scope.trigger({ type: "ZnNewFWContent", content: new_content });

            // CHECK TO SEE IF THE DUMMY INPUT IS PRESENT
            if ($container.children(".zn_group_placeholder").length > 0) {
              $container.children(".zn_group_placeholder").remove();
            }

            if (typeof max_items !== "undefined") {
              var childrens_num = $container.children(".zn_group").length;
              if (childrens_num < max_items) {
                $container.removeClass("zn_add_button_inactive");
              }
            } else {
              $container.removeClass("zn_add_button_inactive");
            }
          } else if (!response.success) {
            alert(response.data.message);
          } else {
            alert("Something went wrong");
            $container.removeClass("zn_add_button_inactive");
          }
        });
      });
    },

    // REMOVE ELEMENT FROM OPTION GROUP
    remove_el: function (scope) {
      var fw = this,
        element = scope ? scope.find(".zn_remove") : $(".zn_remove");

      $(element).on("click", function (e) {
        e.preventDefault();

        // GET THE CONTAINER GROUP
        var el = $(this),
          container = el.closest(".zn_pb_group_content"),
          add_button = container.next(".zn_add_button"),
          max_items = add_button.attr("data-max_items"),
          element_to_delete = el.closest(".zn_group"),
          option_id = $(container)
            .closest(".zn_group_container")
            .data("baseid");

        var callback = function () {
          $(document).trigger("znpb:element:removed", element_to_delete);
          element_to_delete.remove();

          // ADD A DUMMY ELEMENT IN CASE NO ELEMENTS EXISTS
          if (container.children().length === 0) {
            container.append(
              '<input type="hidden" class="zn_group_placeholder" name=' +
                option_id +
                ' value="" />'
            );
          }

          // This needs to be in place for when the new content is actually a group option. It will add the form change data to the pagebuilder
          if (fw.scope.is(".zn_pb_wrapper")) {
            $(".znpb-form-edit-show").find("form").data("changed", true);
          }

          container.zn_sortable_order();

          // Check if we have a max items set
          if (typeof max_items !== "undefined") {
            var childrens_num = container.children(".zn_group").length;
            if (childrens_num < max_items) {
              container.removeClass("zn_add_button_inactive");
            }
          }
        };

        new $.ZnModalConfirm(
          "Are you sure you want to remove this element ?",
          "No",
          "Yes",
          callback
        );
      });
    },

    clone_el: function (scope) {
      var fw = this,
        element = scope
          ? scope.find(".zn_clone_button")
          : $(".zn_clone_button");

      $(element).on("click", function (e) {
        e.preventDefault();

        // GET THE ELEMENT TO BE ADDED
        var el = $(this),
          container = el.closest(".zn_pb_group_content"), // Container
          add_button = container.next(".zn_add_button"),
          max_items = add_button.attr("data-max_items"),
          to_be_cloned = el.closest(".zn_group");

        if (container.hasClass("zn_add_button_inactive")) {
          return false;
        }

        // DISABLE TIYMCE AND REPLACE TINYMCE IDS
        to_be_cloned.find(".zn_tinymce").each(function () {
          var id = $(this).attr("id");
          window.tinyMCE.execCommand("mceRemoveEditor", true, id);
        });

        // Repare textarea
        to_be_cloned.find("textarea").each(function () {
          var textarea_content = $(this).val();
          $(this).html(textarea_content);
        });

        var cloned_data = to_be_cloned.clone(), // Cloned data
          new_content = $(cloned_data);

        // Activate the editors again
        to_be_cloned.find(".zn_tinymce").each(function () {
          var id = $(this).attr("id");
          window.tinyMCE.execCommand("mceAddEditor", true, id);
        });

        // MAKE HIDDEN INPUTS AVAILABLE AGAIN
        new_content
          .find(".zn_class_text")
          .children('input[type="hidden"]')
          .attr("type", "text")
          .next(" div.disabled")
          .remove();

        // Fix icon dropdown not working
        var iconToggles = new_content.find(".zn_icon_op_label");
        iconToggles.each(function (i, element) {
          var newId = $(this).attr("for") + i;
          $(this).attr("for", newId);
          $(this).prev(".zn_icon_op_checkbox").attr("id", newId);
        });
        // Create an event for new content received
        fw.scope.trigger({ type: "ZnNewFWContent", content: new_content });
        fw.repare_modals(new_content);

        container.append(new_content).zn_sortable_order();
        // Allow othersto know we have cloned an element
        el.trigger("znpb:element:cloned", [to_be_cloned, new_content]);
        // Check if we have a max items set
        if (typeof max_items !== "undefined") {
          var childrens_num = container.children(".zn_group").length;
          if (childrens_num >= max_items) {
            container.addClass("zn_add_button_inactive");
          }
        }
      });
    },

    add_g_font: function () {
      var fw = this;

      $(".zn_add_gfont").on("click", function (e) {
        e.preventDefault();

        // GET THE ELEMENT TO BE ADDED
        var selected_font = jQuery(this).prev().val(),
          nonce = ZnAjax.security,
          $conainer = jQuery(".zn_google_fonts_holder");

        // Return if no font was selected
        if (selected_font == "Please select a font") {
          return false;
        }

        var JSONdata = $conainer.find(".znhgfw-repeater-config").text();

        var data = {
          selected_font: selected_font,
          option_schema: JSONdata.trim(),
          action: "znhgfw_html_google_font_add",
          zn_ajax_nonce: nonce,
        };

        jQuery.post(ajaxurl, data, function (response) {
          if (response.success) {
            var new_content = $(response.data.html_markup);

            // Create an event for new content received
            fw.scope.trigger({ type: "ZnNewFWContent", content: new_content });

            $conainer.append(new_content).zn_sortable_order();
          } else if (!response.success) {
            alert(response.data.message);
          } else {
            alert("Something went wrong");
          }
        });
      });
    },

    // REPLACE THE MODAL IDS AND HREF SO THAT THEY WILL POINT CORRECTLY
    repare_modals: function (el) {
      // REPARE MODAL TRIGGERS
      el.find(".zn_modal_trigger").each(function () {
        var id = $(this).attr("href") + new Date().getTime();
        el.find($(this).attr("href")).attr("id", id.replace("#", ""));
        $(this).attr("href", id);
      });

      // Remove quicktags toolbar
      el.find(".quicktags-toolbar").remove();

      // REPARE TINYMCE's ID's
      el.find(".zn_tinymce").each(function () {
        var old_id = $(this).attr("id"), // OLD id
          new_id = old_id + new Date().getTime(), // New id
          replace_string = new RegExp(old_id, "g"), // Replace RegEx
          old_content = $(this).closest(".zn_class_visual_editor"), // Get the old content object
          old_content_html = old_content.html(), // Get the old content HTML
          new_content = old_content_html.replace(replace_string, new_id); // Replace all editor id's to new one

        // Add content back
        old_content.html(new_content);
      });

      // REPARE RADIO BUTTONS
      el.find(".zn_radio").each(function () {
        $(this)
          .find('input[type="radio"]')
          .each(function () {
            var $t = $(this),
              $id = $t.attr("id"),
              $label = $t.next("label"),
              new_id = $id + new Date().getTime();

            $label.attr("for", new_id);
            $t.attr("id", new_id);
          });
      });

      // REPARE TOGGLE2 CHECKBOX
      el.find(".zn_toggle2").each(function () {
        var $t = $(this).find('[type="checkbox"]'),
          $id = $t.attr("id"),
          $label = $t.next("label"),
          new_id = $id + new Date().getTime();

        $label.attr("for", new_id);
        $t.attr("id", new_id);
      });
    },

    // Add sortable
    make_sortable: function (scope) {
      var fw = this,
        element = scope ? scope.find(".zn_group_inner") : $(".zn_group_inner");

      element.sortable({
        handle: "a.zn_group_handle",
        containment: "parent",
        tolerance: "pointer",
        update: function (event, ui) {
          // This needs to be in place for when the new content is actually a group option. It will add the form change data to the pagebuilder
          if (fw.scope.is(".zn_pb_wrapper")) {
            $(".znpb-form-edit-show").find("form").data("changed", true);
          }

          jQuery(this).zn_sortable_order();
        },
      });
    },
    dependencies: function (scope) {
      var fw = this,
        element = scope
          ? scope.find("[data-dependency]")
          : $("[data-dependency]");

      // THIS SCRIPT WILL SHOW AN OPTION BASED ON THE DEPENDENCY
      element.each(function () {
        var el = $(this),
          config = el.data("dependency");

        // Do an initial check
        checkDependency(el, config);
        // Bind change event to options
        triggerChange(config);

        // Checks a dependencies for a given option
        function checkDependency(el, config) {
          // Set initial state
          if (doesQualify(config)) {
            el.slideDown();
          } else {
            el.slideUp();
          }
        }

        // Bind to change trigger for options
        function triggerChange(config) {
          var length = config.length,
            d = 0;

          for (d; d < length; d++) {
            // var option = $( '[data-optionid="'+config[d]['element']+'"]' ),
            var option = el.closest(".zn-modal-form").length
                ? el
                    .closest(".zn-modal-form")
                    .find('[data-optionid="' + config[d]["element"] + '"]')
                : $('[data-optionid="' + config[d]["element"] + '"]'),
              input = option.find(":input"),
              value = $(input).val();

            input.on("change", function () {
              checkDependency(el, config);
            });
          }
        }

        // This function will check the values
        function doesQualify(config) {
          var length = config.length,
            d = 0;

          for (d; d < length; d++) {
            var option = el.closest(".zn-modal-form").length
                ? el
                    .closest(".zn-modal-form")
                    .find('[data-optionid="' + config[d]["element"] + '"]')
                : $('[data-optionid="' + config[d]["element"] + '"]'),
              input = option.find(":input"),
              value = $(input).val();

            // This is a special case for toggle2 option
            if (input.last().attr("type") == "checkbox") {
              value = $(":checked", option).val();
            }

            // Radios and checkboxes have the same name and jQuery only takes the first option value
            // We need to get the value for the checked option
            if (
              $(input).attr("type") == "radio" ||
              $(input).attr("type") == "checkbox"
            ) {
              value = $(":checked", option).val();
            }

            if ($.inArray(value, config[d]["value"]) === -1) {
              return false;
            }
          }

          return true;
        }
      });
    },

    /**
     * Will delete an icon font package
     */
    delete_icon_font: function (scope) {
      var fw = this;

      $(document).on("click", ".js-zn-remove-icon-font", function (e) {
        var font = $(this).parent(),
          data = {
            action: "znhg_remove_icon_font",
            font_name: $(this).data("font_name"),
            security: ZnAjax.security,
          };

        new $.ZnModalConfirm(
          "Are you sure you want to delete this icon package?",
          "No",
          "Yes, delete the icon package",
          function () {
            var $wrapper = $(this).closest(".js-znhg_icon_font_container");

            // Don't proceed if an action is already in progress
            if ($wrapper.hasClass("znhg_icon_font_container--loading")) {
              return;
            }

            // Add a loading class
            $wrapper.addClass("znhg_icon_font_container--loading");

            // Make the ajax call
            jQuery.post(ZnAjax.ajaxurl, data, function (response) {
              // If the font was succesfully deleted
              if (response.success) {
                new $.ZnModalMessage(response.data.message);
                font.remove();
              } else if (!response.success) {
                new $.ZnModalMessage(response.data.message);
              } else {
                new $.ZnModalMessage(
                  "There was a problem downloading the icons !"
                );
              }

              // Remove the loading class
              $wrapper.removeClass("znhg_icon_font_container--loading");
            });
          }
        );
      });
    },

    /**
     * Will download an icon font package
     */
    download_icon_font: function () {
      var fw = this;

      $(document).on("click", ".js-zn-download-icon-font", function (e) {
        var $wrapper = $(this).closest(".js-znhg_icon_font_container");

        // Don't proceed if an action is already in progress
        if ($wrapper.hasClass("znhg_icon_font_container--loading")) {
          return;
        }

        // Add a loading class
        $wrapper.addClass("znhg_icon_font_container--loading");

        var data = {
          action: "znhg_get_download_icon_font_url",
          font_name: $(this).data("font_name"),
          security: ZnAjax.security,
        };

        // Make the ajax call
        jQuery.post(ZnAjax.ajaxurl, data, function (response) {
          // If we got an error
          if (response.success) {
            window.location.assign(response.data.archive_url);
          } else if (!response.success) {
            new $.ZnModalMessage(response.data.message);
          } else {
            new $.ZnModalMessage("There was a problem downloading the icons !");
          }

          // Remove the loading class
          $wrapper.removeClass("znhg_icon_font_container--loading");
        });
      });
    },

    // NOT AJAXIFIED ... IF NEDED ADD A SCOPE AND ADD IT TO THE LIST OF REFRESHED EVENTS
    upload_icon_font: function () {
      var fw = this,
        trigger = $(".zn_file_upload");

      trigger.on("click", function (e) {
        e.preventDefault();

        if (fw.file_uploader) {
          fw.file_uploader.open();
          return;
        }

        var button = jQuery(this),
          title = button.data("title"),
          zn_button = button.data("button"),
          file_type = button.data("file_type"),
          field = button.prev();

        fw.file_uploader = wp.media.frames.file_frame = wp
          .media({
            title: title,
            button: {
              text: zn_button,
            },
            library: {
              type: file_type,
            },
            multiple: false,
          })
          .on("select", function () {
            var attachment = fw.file_uploader
              .state()
              .get("selection")
              .first()
              .toJSON();

            var data = {
              action: "znhg_upload_icon_package",
              attachment: attachment,
              security: ZnAjax.security,
            };

            // Make the ajax call
            jQuery.post(ZnAjax.ajaxurl, data, function (response) {
              if (response.success) {
                new $.ZnModalMessage(response.data.message);
                $(".uploads_container").append(response.data.html);
              } else {
                new $.ZnModalMessage(
                  "There was a problem uploading the icons !"
                );
              }
            });
          });

        fw.file_uploader.open();
      });
    },

    copyToClipboard: function (content) {
      $(content)
        .find("[data-clipboard-text]")
        .on("click", function (e) {
          e.preventDefault();
          var thisText = $(this).attr("data-clipboard-text"),
            $temp = $("<input>");
          $("body").append($temp);
          $temp.val(thisText).select();
          document.execCommand("copy");
          $temp.remove();
          $(this).addClass("u-text-copied");
        });
    },
  };

  /*
   *	INIT the JS framework
   */

  $(function () {
    $.zn_html = new $.ZnHtml();
    //for(var b in window) {if(window.hasOwnProperty(b)) console.log(b); }
  });
})(jQuery);

/*
 *	START THE MAIN FUNCTIONS
 *
 *	CONTENTS :
 *	1. AJAX CALLS
 *	2. PLUGINS ENABLER
 *
 */
(function ($) {
  jQuery.fn.zn_sortable_order = function () {
    baseid = "";
    if (jQuery(this).attr("data-baseid") !== undefined) {
      baseid = jQuery(this).attr("data-baseid");
    } else {
      baseid = jQuery(this).parents("div.zn_group:first").attr("data-baseid");
    }

    // PREPARE THE BASEID
    search_baseid = baseid.replace(/(\[)/g, "\\[");
    str = "(" + search_baseid + "\\[\\d+\\])";
    var reg = new RegExp(str);

    this.children("div.zn_group").each(function (idx) {
      // CHANGE THE BASE ID
      jQuery(this).attr("data-baseid", baseid + "[" + idx + "]");

      jQuery(this)
        .find("[data-baseid]")
        .each(function () {
          //console.log(baseid +' '+ this.name+'  '+this.name.replace(reg, baseid + '[' + idx + ']'));
          jQuery(this).attr(
            "data-baseid",
            jQuery(this)
              .attr("data-baseid")
              .replace(reg, baseid + "[" + idx + "]")
          );
        });

      // CHANGE THE INPUT BASE ID's
      var $inp = jQuery(this).find(":input");
      $inp.each(function () {
        //console.log(baseid +' '+ this.name+'  '+this.name.replace(reg, baseid + '[' + idx + ']'));
        this.name = this.name.replace(reg, baseid + "[" + idx + "]");
      });
    });
  };

  $.fn.dragKeyField = function (options) {
    // defaults
    var def = $.extend(
      {
        hasUnit: true,
        unit: "px",
        keyup: true,
        drag: true,
        min: -1000,
        max: 1000,
      },
      options || {}
    );

    var defaultUnit = def.hasUnit ? def.unit : "";

    if (def.keyup) {
      this.on("keyup", function (event) {
        var currTarget = $(event.currentTarget),
          currTargetVal =
            currTarget.val() !== ""
              ? currTarget.val().trim()
              : "0" + defaultUnit,
          currTargetVal_numer = parseInt(currTargetVal),
          currTargetVal_unit = def.hasUnit
            ? currTargetVal.replace(currTargetVal_numer, "")
            : "",
          currTargetVal_step = 1,
          disable_negative = currTarget.is('[data-disable-negative="yes"]')
            ? true
            : false;

        if (disable_negative && def.min < 0) {
          def.min = 0;
        }

        // Check if shift is pressed and change to 10
        if (event.shiftKey) {
          currTargetVal_step = 10;
        }
        // get key and do the math
        switch (event.which) {
          // up
          case 38:
            var sum_upwards = currTargetVal_numer + currTargetVal_step;
            currTargetVal = sum_upwards + currTargetVal_unit;
            if (sum_upwards < def.min || sum_upwards > def.max) return;
            currTarget.val(currTargetVal);
            break;
          // down
          case 40:
            var sum_downwards = currTargetVal_numer - currTargetVal_step;
            currTargetVal = sum_downwards + currTargetVal_unit;
            if (sum_downwards < def.min || sum_downwards > def.max) return;
            currTarget.val(currTargetVal);
            break;
          // exit this handler for other keys
          default:
            return;
        }
        // prevent the default action (scroll / move caret)
        event.preventDefault();
        currTarget.trigger("change");
      });
    }

    if (def.drag) {
      this.on("mousedown", function (e) {
        if (e.which !== undefined && e.which !== 1) return false;

        var disable_negative = $(e.currentTarget).is(
          '[data-disable-negative="yes"]'
        )
          ? true
          : false;
        if (disable_negative && def.min < 0) {
          def.min = 0;
        }
        $(document).on("mouseup", function () {
          $(document).off("mousemove").off("mouseup");
          $("body").css({ cursor: "" });
        });

        var unit = def.hasUnit ? this.value.replace(/[0-9\-]/g, "") : "";

        if (def.hasUnit && unit === "") {
          unit = defaultUnit;
        }

        $(document).on(
          "mousemove",
          {
            el: this,
            cur: parseInt(this.value !== "" ? this.value : 0),
            unit: unit,
            top: e.clientY,
          },
          function (e) {
            var offset = e.clientY - e.data.top;
            var offset_sum = parseInt(e.data.cur - offset);

            if (offset_sum < def.min) {
              offset_sum = 0;
            } else if (offset_sum < def.min || offset_sum > def.max) {
              return;
            }

            e.data.el.value = offset_sum + e.data.unit;
            $(e.data.el).trigger("change");
          }
        );

        $("body").css({ cursor: "ns-resize" });

        $(window)
          .off("mouseup")
          .on("mouseup", function () {
            $(document).off("mousemove");
            $(window).off("mouseup");
          });
      });
    }

    return this;
  };
})(jQuery);

// Uploading files
var file_frame;

jQuery("body").on("click", ".zn-remove-image", function () {
  jQuery(this)
    .parents(".zn_option_content")
    .find(".logo_upload_input")
    .val("")
    .trigger("change");
  jQuery(this)
    .parent()
    .html(
      'Nothing selected...<a class="zn-remove-image" data-toggle="tooltip" data-title="Remove Image" href="#"></a>'
    );
  return false;
});

jQuery("body").on("click", ".zn_upload_image_button", function (event) {
  event.preventDefault();
  var button = jQuery(this),
    multiple = button.data("multiple"),
    title = button.data("title"),
    zn_button = button.data("button"),
    field = button.prev();

  // Create the media frame.
  file_frame = wp.media.frames.file_frame = wp.media({
    title: title,
    button: {
      text: zn_button,
    },
    multiple: multiple,
  });

  file_frame.on("close", function () {
    file_frame.detach();
  });

  // When an image is selected, run a callback.
  file_frame.on("select", function () {
    // We set multiple to false so only get one image from the uploader
    attachment = file_frame.state().get("selection").first().toJSON();

    // Do somethign with the images
    if (!multiple) {
      //console.log(attachment);
      if (field.data("id") === true) {
        field.val(attachment.id).trigger("change");
      } else {
        field.val(attachment.url).trigger("change");
      }

      image =
        '<button title="Close (Esc)" type="button" class=" zn-remove-image">&#215;</button><img class="zn_mu_image" src="' +
        attachment.url +
        '" />';
      field.parent().children(".zn-image-holder").html(image);
    } else {
    }
    // Restore the main post ID
    //wp.media.model.settings.post.id = wp_media_post_id;
  });

  // Finally, open the modal
  file_frame.open();
});

/* Link media button */
jQuery("body").on("click", ".zn_media_link_button_trigger", function (event) {
  var file_frame;
  event.preventDefault();
  var button = jQuery(this),
    title = button.data("title"),
    zn_button = button.data("button"),
    targetFieldUrl = jQuery("#" + button.data("targetUrl")),
    targetTitleField = jQuery("#" + button.data("targetTitle"));

  // Create the media frame.
  file_frame = wp.media.frames.file_frame = wp.media({
    title: title,
    button: {
      text: zn_button,
    },
    multiple: false,
  });

  file_frame.on("close", function () {
    file_frame.detach();
  });

  // When an image is selected, run a callback.
  file_frame.on("select", function () {
    // We set multiple to false so only get one image from the uploader
    var attachment = file_frame.state().get("selection").first().toJSON();
    // Update references
    targetFieldUrl.val(attachment.url).trigger("change");
    targetTitleField.val(attachment.title).trigger("change");
  });

  // Finally, open the modal
  file_frame.open();
});

// Restore the main ID when the add media button is pressed
//jQuery('a.add_media').on('click', function() {
//wp.media.model.settings.post.id = wp_media_post_id;
//file_frame.remove(0);
//});
