

AwliWidget = {
  load: function () {
    var AWLI_LOAD_EVENT = 'awli-widget-load',
        AWLI_WIDGET_CLASS = 'IN-Awli-widget',
        paramsElem,
        params = {},
        // replace the endpoint with the url passed from server side
        endpoint = 'https://www.linkedin.com/mjobs/awli/index',
        host = 'https://www.linkedin.com',

    init = function () {
      // validate and set widget params
      validateAndSetWidgetInputParams();

      // create frame
      createFrame();
    },

    validateAndSetWidgetInputParams = function() {
      // client passes parameters to invoke the widget via a script tag. It is required to successfully invoke the widget.
      paramsElem = document.querySelector('script[type="IN/AwliWidget"]');
      if (!paramsElem) {
        throw new Error("Widget needs a script tag element with type='IN/AwliWdiget' to provide parameters to work!");
      }
      var apiKey = paramsElem.getAttribute('data-api-key'),
          companyJobCode = paramsElem.getAttribute('data-company-job-code'),
          companyToken = paramsElem.getAttribute('data-company-token'),
          integrationContext = paramsElem.getAttribute('data-integration-context'),
          mode = paramsElem.getAttribute('data-mode'),
          size = paramsElem.getAttribute('data-size'),
          color = paramsElem.getAttribute('data-color'),
          allowSignInMode = paramsElem.getAttribute('data-allow-sign-in');
      AwliWidget.callback = paramsElem.getAttribute('data-callback-method');
      AwliWidget.defaultButtonCallback = paramsElem.getAttribute('data-default-button-callback');

      if (!apiKey) {
        throw new Error("Widget requires apiKey to work!");
      }

      if (!companyJobCode) {
        throw new Error("Widget requires company job code to work!");
      }

      if (!companyToken && !integrationContext) {
        throw new Error("Widget requires either companyToken or integrationContext to work!");
      }

      if (!mode) {
        throw new Error("Widget requires a mode to work! Examples are BUTTON, BUTTON_DATA, DATA, CONVERSION etc.");
      }

      params = {
        apiKey: apiKey,
        companyJobCode: companyJobCode,
        mode: mode,
        size: size,
        color: color
      };

      // If allowSignInMode is not specified (either true/false) then we don't want to pass as params
      if (allowSignInMode !== null) {
        params.allowSignInMode = allowSignInMode;
      }

      if (integrationContext) {
        params.integrationContext = integrationContext;
      }

      if (companyToken) {
        params.companyToken = companyToken;
      }
    },

    createFrame = function() {

      _removeCurrentWidgets();
      var frameWrapperOuter = document.createElement('span'),
          frameWrapperInner = document.createElement('span'),
          widgetFrame = document.createElement('iframe');

      frameWrapperOuter.setAttribute('class', AWLI_WIDGET_CLASS);
      frameWrapperOuter.setAttribute('style', 'line-height: 1; vertical-align: baseline; display: inline-block; width:auto;');

      frameWrapperInner.setAttribute('style', 'padding: 0 !important; margin: 0 !important; text-indent: 0 !important; display: inline-block !important; vertical-align: baseline !important; font-size: 1px !important;');
      frameWrapperInner.appendChild(widgetFrame);

      frameWrapperOuter.appendChild(frameWrapperInner);

      widgetFrame.setAttribute('frameborder', '0');
      widgetFrame.setAttribute('scrolling', 'no');
      widgetFrame.setAttribute('style', 'width: 100%; height: 0; display: inline-block;');
      widgetFrame.src = _generateIframeSrc(endpoint, params);

      window.addEventListener('message', function(event) {
        var data;
        if (event.origin !== host) {
          return;
        }

        data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
        if (data.operation) {
          if (data.operation === 'defaultButton' && AwliWidget.defaultButtonCallback) {
            _executeFunctionByName(AwliWidget.defaultButtonCallback, window, data.data, data.signature);
          }

          else if (data.operation === 'buttonClick' && AwliWidget.callback) {
            _executeFunctionByName(AwliWidget.callback, window, data.data, data.signature);
          }

          else if (data.operation === 'dataFetch' && AwliWidget.callback) {
            _executeFunctionByName(AwliWidget.callback, window, data.data, data.signature);
          }

          else if (data.operation === 'resizeIframe') {
            // for some reason, the iframe has an empty space on the right for the scrollbar. If we set iframe to the side of the content,
            // the actual content element size will be original content width - scrollbar width. Adding another 20px to compensate for the width.
            var iframeWidth = data.data.width + 20;
            // Using margin of 5px and compensate height accordingly for frame.
            var iframeHeight = data.data.height + 10;
            widgetFrame.setAttribute('style', 'width: ' + iframeWidth + 'px; height: ' + iframeHeight +'px;');
          }

          else if (data.operation === 'reload') {
            // track memberSignedIn and company apply url on widget reload.
            params['memberSignedIn'] = (data.data && data.data.memberSignedIn) || false;
            params['companyApplyUrl'] = (data.data && data.data.companyApplyUrl) || '';
            // After user sign-in through the window popup and closes the popup,
            // we send a signal to ATS page to reload the widget so that it reflects
            // sign-in state and it shows Apply with LinkedIn button.
            widgetFrame.src = _generateIframeSrc(endpoint, params);
          }
        }
      }, false);

      paramsElem.parentElement.insertBefore(frameWrapperOuter, paramsElem);
    },

    _removeCurrentWidgets = function () {
      // to make sure there is no existing awli widget on this page
      var currentWidgets = document.getElementsByClassName(AWLI_WIDGET_CLASS);
      for (var i = 0; i < currentWidgets.length; i++) {
        var widget = currentWidgets[i];
        widget.parentNode.removeChild(widget);
      }
    },

    /**
    * helper function for us to call the callback function provided by the client to
    * handle the message from the widget javascript.
    *
    * It takes a name of a method, a context, and invokes the function within the context
    */
    _executeFunctionByName = function (functionName, context /*, args */) {
      var args = [].slice.call(arguments).splice(2),
          namespaces = functionName.split("."),
          func = namespaces.pop();
      for(var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
      }
      return context[func].apply(context, args);
    },

    /**
    * Based on the parameters and basic url of our javascript endpoint to generate the target url to render our widget
    */
    _generateIframeSrc = function(url, params) {
      var pairs = [],
          concatParams,
          resultUrl;
      for (var pair in params) {
        var joined = pair + "=" + params[pair];
        pairs.push(joined);
      }
      concatParams = pairs.join('&');
      if (url.indexOf('?') > -1) {
        resultUrl = url + "&" + concatParams;
      } else {
        resultUrl = url + "?" + concatParams;
      }
      return resultUrl;
    };

    if (document.readyState === 'complete') {
      init();
    } else {
      window.addEventListener('load', init, false);
      // add a custom event, so in case of single page app, the client can send this custom event to trigger a reload
      // of the widget.
      window.addEventListener(AWLI_LOAD_EVENT, init, false);
    }
  }
};
AwliWidget.load();
