(function() {
  function formatBytes(bytes) {
    if (!bytes && bytes !== 0) {
      return '';
    }

    var units = ['B', 'KB', 'MB', 'GB'];
    var size = bytes;
    var unit = 0;
    while (size >= 1024 && unit < units.length - 1) {
      size = size / 1024;
      unit++;
    }

    return (unit === 0 ? size : size.toFixed(1)) + ' ' + units[unit];
  }

  function normalizeUrl(url) {
    url = (url || '').trim();
    if (url && !/^[a-z][a-z0-9+.-]*:\/\//i.test(url)) {
      url = 'https://' + url;
    }
    return url;
  }

  function forEachNode(nodes, callback) {
    Array.prototype.forEach.call(nodes, callback);
  }

  function isInteractiveTarget(target, boundary) {
    while (target && target !== boundary) {
      if (target.tagName && /^(A|BUTTON|INPUT|TEXTAREA|SELECT|LABEL)$/i.test(target.tagName)) {
        return true;
      }
      target = target.parentNode;
    }
    return false;
  }

  function translate(text) {
    if (window.en4 && en4.core && en4.core.language && typeof en4.core.language.translate === 'function') {
      return en4.core.language.translate(text);
    }
    return text;
  }

  function clearRemoveFlag(root) {
    var removeElementId = root.getAttribute('data-remove-element');
    if (!removeElementId) return;

    var removeElement = document.getElementById(removeElementId);
    if (removeElement && removeElement.type === 'checkbox') {
      removeElement.checked = false;
    }
  }

  function setRemoveFlag(root) {
    var removeElementId = root.getAttribute('data-remove-element');
    if (!removeElementId) return;

    var removeElement = document.getElementById(removeElementId);
    if (removeElement && removeElement.type === 'checkbox') {
      removeElement.checked = true;
    }
  }

  function showPreview(root, src, size) {
    var preview = root.querySelector('[data-media-upload-preview]');
    var image = root.querySelector('[data-media-upload-preview-img]');
    var sizeElement = root.querySelector('[data-media_uploader_box_hint]');
    if (!preview || !image) return;

    image.src = src;
    image.style.display = '';
    preview.style.display = '';
    root.classList.add('has-media-preview');

    if (sizeElement) {
      sizeElement.textContent = size ? formatBytes(size) : '';
    }
  }

  function hidePreview(root) {
    var preview = root.querySelector('[data-media-upload-preview]');
    var image = root.querySelector('[data-media-upload-preview-img]');
    var sizeElement = root.querySelector('[data-media_uploader_box_hint]');
    if (preview) preview.style.display = 'none';
    if (image) {
      image.removeAttribute('src');
      image.style.display = 'none';
    }
    if (sizeElement) sizeElement.textContent = '';
    root.classList.remove('has-media-preview');
  }

  function chooseFile(input, capture) {
    if (capture) {
      input.setAttribute('capture', 'environment');
    } else {
      input.removeAttribute('capture');
    }
    input.click();
  }

  function closeCameraModal(modal, stream) {
    if (stream && stream.getTracks) {
      stream.getTracks().forEach(function(track) {
        track.stop();
      });
    }
    if (modal && modal.parentNode) {
      modal.parentNode.removeChild(modal);
    }
  }

  function setCameraPhoto(root, input, cameraDataInput, urlInput, dataUrl) {
    input.value = '';
    if (urlInput) urlInput.value = '';
    if (cameraDataInput) cameraDataInput.value = dataUrl;
    clearRemoveFlag(root);
    showPreview(root, dataUrl, '');
  }

  function showPermissionModal(onRetry) {
    // Prevent duplicate modals
    var existingModal = document.querySelector('.media_uploader_camera_permission_modal');
    if (existingModal && existingModal.parentNode) {
      existingModal.parentNode.removeChild(existingModal);
    }

    var modal = document.createElement('div');
    modal.className = 'media_uploader_camera_modal media_uploader_camera_permission_modal';
    modal.innerHTML = '' +
      '<div class="media_uploader_camera_modal_container" style="text-align: center; padding: 20px;">' +
        '<h3>' + translate('Camera Access Needed') + '</h3>' +
        '<p style="margin: 15px 0; color: #666;">' + 
          translate('Camera permission is blocked or unavailable. Please check System Settings and browser permissions to enable camera access.') +
        '</p>' +
        '<div class="media_uploader_camera_modal_actions">' +
          '<button class="btn btn-primary" type="button" data-camera-try-again>' + translate('Try Again') + '</button>' +
          '<button class="btn btn-alt" type="button" data-camera-close>' + translate('Cancel') + '</button>' +
        '</div>' +
      '</div>';
    document.body.appendChild(modal);

    modal.querySelector('[data-camera-try-again]').addEventListener('click', function() {
      if (modal.parentNode) modal.parentNode.removeChild(modal);
      if (typeof onRetry === 'function') onRetry();
    });

    modal.querySelector('[data-camera-close]').addEventListener('click', function() {
      if (modal.parentNode) modal.parentNode.removeChild(modal);
    });
  }

  function openCamera(root, input, cameraDataInput, urlInput) {
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      chooseFile(input, true);
      return;
    }

    // Check query permissions API where supported (macOS Chrome support)
    if (navigator.permissions && navigator.permissions.query) {
      navigator.permissions.query({ name: 'camera' }).then(function(result) {
        if (result.state === 'denied') {
          showPermissionModal(function() {
            openCamera(root, input, cameraDataInput, urlInput);
          });
          return;
        }
        requestCameraStream(root, input, cameraDataInput, urlInput);
      }).catch(function() {
        requestCameraStream(root, input, cameraDataInput, urlInput);
      });
    } else {
      requestCameraStream(root, input, cameraDataInput, urlInput);
    }
  }

  function requestCameraStream(root, input, cameraDataInput, urlInput) {
    navigator.mediaDevices.getUserMedia({ video: true, audio: false })
      .then(function(stream) {
        var modal = document.createElement('div');
        modal.className = 'media_uploader_camera_modal';
        modal.innerHTML = '' +
          '<div class="media_uploader_camera_modal_container">' +
            '<div class="media_uploader_camera_modal_stage">' +
              '<video autoplay playsinline muted></video>' +
              '<canvas style="display:none;"></canvas>' +
            '</div>' +
            '<div class="media_uploader_camera_modal_actions">' +
              '<button class="btn btn-primary" type="button" data-camera-capture>' + translate('Capture') + '</button>' +
              '<button class="btn btn-primary" type="button" data-camera-use style="display:none;">' + translate('Use Photo') + '</button>' +
              '<button class="btn btn-primary" type="button" data-camera-retake style="display:none;">' + translate('Retake') + '</button>' +
              '<button class="btn btn-alt" type="button" data-camera-close>' + translate('Cancel') + '</button>' +
            '</div>' +
          '</div>';
        document.body.appendChild(modal);

        var video = modal.querySelector('video');
        var canvas = modal.querySelector('canvas');
        var captureButton = modal.querySelector('[data-camera-capture]');
        var useButton = modal.querySelector('[data-camera-use]');
        var retakeButton = modal.querySelector('[data-camera-retake]');
        var closeButton = modal.querySelector('[data-camera-close]');
        var capturedDataUrl = '';
        var activeStream = stream;

        if ('srcObject' in video) {
          video.srcObject = stream;
        } else {
          video.src = window.URL.createObjectURL(stream);
        }

        // Play video safely (handles macOS Chrome autoplay policies)
        video.play().catch(function(e) {
          console.warn("Video play error:", e);
        });

        captureButton.addEventListener('click', function() {
          var width = video.videoWidth || 640;
          var height = video.videoHeight || 480;
          canvas.width = width;
          canvas.height = height;
          canvas.getContext('2d').drawImage(video, 0, 0, width, height);
          capturedDataUrl = canvas.toDataURL('image/jpeg', 0.9);
          video.style.display = 'none';
          canvas.style.display = '';
          captureButton.style.display = 'none';
          useButton.style.display = '';
          retakeButton.style.display = '';
        });

        useButton.addEventListener('click', function() {
          if (capturedDataUrl) {
            setCameraPhoto(root, input, cameraDataInput, urlInput, capturedDataUrl);
          }
          closeCameraModal(modal, activeStream);
        });

        retakeButton.addEventListener('click', function() {
          capturedDataUrl = '';
          canvas.style.display = 'none';
          video.style.display = '';
          captureButton.style.display = '';
          useButton.style.display = 'none';
          retakeButton.style.display = 'none';
        });

        closeButton.addEventListener('click', function() {
          closeCameraModal(modal, activeStream);
        });
      })
      .catch(function(err) {
        console.warn("Camera access error:", err);
        var errName = err.name || err.message;
        if (errName === 'NotAllowedError' || errName === 'PermissionDeniedError' || errName === 'NotReadableError') {
          showPermissionModal(function() {
            openCamera(root, input, cameraDataInput, urlInput);
          });
        } else {
          chooseFile(input, true);
        }
      });
  }

  function initMediaUpload(root) {
    if (!root || root.getAttribute('data-media-upload-ready') === '1') return;

    root.setAttribute('data-media-upload-ready', '1');

    var input = root.querySelector('.core-media-upload-input');
    var dropzone = root.querySelector('.media-upload-dropzone');
    var urlInput = root.querySelector('[data-media_uploader_upload_url]');
    var urlSubmit = root.querySelector('[data-media_uploader_upload_url-submit]');
    var removeButton = root.querySelector('[data-media-upload-remove]');
    var cameraDataInput = root.querySelector('[data-media-upload-camera-data]');

    var dragCounter = 0;

    if (!input || !dropzone) return;

    forEachNode(root.querySelectorAll('[data-media-upload-trigger]'), function(button) {
      button.addEventListener('click', function(event) {
        event.preventDefault();
        chooseFile(input, false);
      });
    });

    var cameraButton = root.querySelector('[data-media-upload-camera]');
    if (cameraButton) {
      cameraButton.addEventListener('click', function(event) {
        event.preventDefault();
        openCamera(root, input, cameraDataInput, urlInput);
      });
    }

    input.addEventListener('change', function() {
      var file = input.files && input.files[0];
      if (!file || file.type.indexOf('image/') !== 0) return;

      if (urlInput) urlInput.value = '';
      if (cameraDataInput) cameraDataInput.value = '';
      clearRemoveFlag(root);
      showPreview(root, window.URL.createObjectURL(file), file.size);
    });

    dropzone.addEventListener('click', function(event) {
      if (isInteractiveTarget(event.target, dropzone)) return;
      chooseFile(input, false);
    });

    dropzone.addEventListener('keydown', function(event) {
      if (event.key === 'Enter' || event.key === ' ') {
        event.preventDefault();
        chooseFile(input, false);
      }
    });

    dropzone.addEventListener('dragenter', function(event) {
      event.preventDefault();
      dragCounter++;
      root.classList.add('is-dragover');
    });

    dropzone.addEventListener('dragover', function(event) {
      event.preventDefault();
      root.classList.add('is-dragover');
    });

    dropzone.addEventListener('dragleave', function(event) {
      event.preventDefault();
      dragCounter--;
      if (dragCounter <= 0) {
        root.classList.remove('is-dragover');
        dragCounter = 0;
      }
    });

    dropzone.addEventListener('drop', function(event) {
      event.preventDefault();
      dragCounter = 0;
      root.classList.remove('is-dragover');
      var files = event.dataTransfer && event.dataTransfer.files;
      if (!files || !files.length || files[0].type.indexOf('image/') !== 0) return;

      try {
        input.files = files;
      } catch (e) {}

      if (urlInput) urlInput.value = '';
      if (cameraDataInput) cameraDataInput.value = '';
      clearRemoveFlag(root);
      showPreview(root, window.URL.createObjectURL(files[0]), files[0].size);
    });

    if (urlInput) {
      urlInput.addEventListener('paste', function(event) {
        handlePastedImage(event, root, input, urlInput, cameraDataInput);
      });
    }

    dropzone.addEventListener('paste', function(event) {
      handlePastedImage(event, root, input, urlInput, cameraDataInput);
    });

    if (urlSubmit && urlInput) {
      urlSubmit.addEventListener('click', function(event) {
        event.preventDefault();
        var url = normalizeUrl(urlInput.value);
        if (!url) return;

        input.value = '';
        if (cameraDataInput) cameraDataInput.value = '';
        urlInput.value = url;
        clearRemoveFlag(root);
        showPreview(root, url, '');
      });

      urlInput.addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
          event.preventDefault();
          urlSubmit.click();
        }
      });
    }

    if (removeButton) {
      removeButton.addEventListener('click', function(event) {
        event.preventDefault();
        input.value = '';
        if (urlInput) urlInput.value = '';
        if (cameraDataInput) cameraDataInput.value = '';
        setRemoveFlag(root);
        hidePreview(root);
      });
    }
  }

  function handlePastedImage(event, root, input, urlInput, cameraDataInput) {
    var clipboardItems = event.clipboardData && event.clipboardData.items;
    if (!clipboardItems || !clipboardItems.length) return;

    for (var i = 0; i < clipboardItems.length; i++) {
      var item = clipboardItems[i];
      if (item.type.indexOf('image/') === 0) {
        event.preventDefault();
        var file = item.getAsFile();
        if (!file) return;

        var dataTransfer = new DataTransfer();
        dataTransfer.items.add(file);

        try {
          input.files = dataTransfer.files;
        } catch (e) {}

        if (urlInput) urlInput.value = '';
        if (cameraDataInput) cameraDataInput.value = '';

        clearRemoveFlag(root);
        showPreview(root, window.URL.createObjectURL(file), file.size);
        return;
      }
    }
  }

  function initAllMediaUploads(scope) {
    var container = scope && scope.querySelectorAll ? scope : document;
    forEachNode(container.querySelectorAll('[data-core-media-upload]'), initMediaUpload);
  }

  window.EngineMediaUpload = {
    init: initAllMediaUploads
  };

  if (window.en4 && en4.core && en4.core.runonce) {
    en4.core.runonce.add(function() {
      initAllMediaUploads(document);
    });
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function() {
      initAllMediaUploads(document);
    });
  } else {
    initAllMediaUploads(document);
  }
})();