/**
 * PDF Annotation Viewer directive.
 * Written in ES5 for ngAnnotate compatibility.
 */
var module;
try {
  module = angular.module('docs');
} catch (e) {
  module = angular.module('share');
}

module.directive('pdfAnnotationViewer', function ($stateParams, Restangular, $timeout, $http) {
  return {
    restrict: 'E',
    scope: {
      fileId: '=',
      documentId: '=',
      shareId: '='
    },
    template: '<div class="pdf-annotation-container">' +
      '<div class="pdf-toolbar">' +
        '<div class="btn-group">' +
          '<button class="btn btn-default" ng-class="{active: tool === \'cursor\'}" ng-click="setTool(\'cursor\')" uib-tooltip="Cursor"><span class="fas fa-mouse-pointer"></span></button>' +
          '<button class="btn btn-default" ng-class="{active: tool === \'pencil\'}" ng-click="setTool(\'pencil\')" uib-tooltip="Pencil"><span class="fas fa-pencil-alt"></span></button>' +
          '<button class="btn btn-default" ng-class="{active: tool === \'highlight\'}" ng-click="setTool(\'highlight\')" uib-tooltip="Highlight"><span class="fas fa-highlighter"></span></button>' +
          '<button class="btn btn-default" ng-class="{active: tool === \'text\'}" ng-click="setTool(\'text\')" uib-tooltip="Text"><span class="fas fa-font"></span></button>' +
          '<button class="btn btn-default" ng-class="{active: tool === \'eraser\'}" ng-click="setTool(\'eraser\')" uib-tooltip="Eraser (click to delete)"><span class="fas fa-eraser"></span></button>' +
        '</div>' +
        '<div class="btn-group">' +
          '<button class="btn btn-default" ng-click="zoomOut()"><span class="fas fa-search-minus"></span></button>' +
          '<span class="btn btn-placeholder">{{ zoom * 100 | number:0 }}%</span>' +
          '<button class="btn btn-default" ng-click="zoomIn()"><span class="fas fa-search-plus"></span></button>' +
        '</div>' +
        '<div class="btn-group pull-right">' +
          '<button class="btn btn-default" ng-click="exportPdf()" ng-disabled="exporting" uib-tooltip="Export as PDF">' +
            '<span class="fas fa-file-pdf"></span> {{ exporting === \'pdf\' ? \'Exporting...\' : \'PDF\' }}' +
          '</button>' +
          '<button class="btn btn-danger" ng-click="clearAllAnnotations()" ng-disabled="saving || shareId || annotations.length === 0" uib-tooltip="Clear all annotations">' +
            '<span class="fas fa-trash"></span>' +
          '</button>' +
          '<button class="btn btn-warning" ng-click="saveAsVersion()" ng-disabled="exporting || saving || shareId" uib-tooltip="Save as a new PDF version in Teedy">' +
            '<span class="fas fa-file-upload"></span> {{ exporting === \'version\' ? \'Uploading...\' : \'Save Version\' }}' +
          '</button>' +
          '<button class="btn btn-primary" ng-click="saveAnnotations()" ng-disabled="saving || shareId">' +
            '<span class="fas fa-save"></span> {{ (saving ? \'Saving...\' : \'Save\') }}' +
          '</button>' +
        '</div>' +
      '</div>' +
      '<div class="pdf-viewer-scroll">' +
        '<div class="pdf-pages-container" id="pdf-pages"></div>' +
      '</div>' +
    '</div>' +
    '<style>' +
      '.pdf-annotation-container { display: flex; flex-direction: column; height: 100%; position: relative; background: #525659; }' +
      '.pdf-toolbar { background: #323639; padding: 10px; color: white; display: flex; gap: 10px; align-items: center; z-index: 100; box-shadow: 0 2px 5px rgba(0,0,0,0.3); }' +
      '.pdf-viewer-scroll { flex: 1; overflow: auto; padding: 20px; }' +
      '.pdf-pages-container { display: flex; flex-direction: column; align-items: center; gap: 20px; }' +
      '.pdf-page-wrapper { position: relative; box-shadow: 0 0 10px rgba(0,0,0,0.5); background: white; }' +
      '.pdf-canvas { display: block; }' +
      '.annotation-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }' +
      '.annotation-layer.active { pointer-events: all; cursor: crosshair; }' +
      '.annotation-layer.tool-cursor { cursor: default; }' +
      '.pdf-text-input { position: absolute; border: 1px solid #2aabd2; background: rgba(255,255,255,0.8); z-index: 200; outline: none; padding: 2px; }' +
    '</style>',
    link: function (scope, element) {
      scope.tool = 'cursor';
      scope.zoom = 1.0;
      scope.annotations = [];
      scope.saving = false;
      scope.exporting = null;

      var pdfDoc = null;
      var pages = [];
      var currentRenderId = 0;
      var deregisterDocIdWatch = null;
      var isDrawing = false;
      var currentPath = null;
      var currentElement = null;

      function getDocId() {
        return scope.documentId || $stateParams.documentId || $stateParams.id;
      }

      // Initialize PDF.js
      pdfjsLib.GlobalWorkerOptions.workerSrc = 'lib/pdf.worker.min.js';

      // Fetch annotations from server
      function fetchAnnotations(docId) {
        if (!docId) return Promise.resolve([]);
        return Restangular.one('comment', docId).get({ share: scope.shareId }).then(function (data) {
          var annoComment = null;
          for (var i = 0; i < data.comments.length; i++) {
            if (data.comments[i].content.indexOf('[ANNOTATION]') === 0) {
              annoComment = data.comments[i];
              break;
            }
          }
          if (annoComment) {
            try {
              return JSON.parse(annoComment.content.replace('[ANNOTATION]', ''));
            } catch (e) {
              console.error('Error parsing annotations:', e);
            }
          }
          return [];
        }, function () { return []; });
      }

      // Render annotations for a single page
      function renderPageAnnotations(pageNum, svg) {
        svg.innerHTML = '';
        var pageAnnos = [];
        for (var i = 0; i < scope.annotations.length; i++) {
          if (scope.annotations[i].page === pageNum) {
            pageAnnos.push({ a: scope.annotations[i], idx: i });
          }
        }

        pageAnnos.forEach(function (item) {
          var a = item.a;
          var idx = item.idx;
          var el;
          if (a.type === 'pencil' || a.type === 'highlight') {
            el = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            el.setAttribute('fill', 'none');
            el.setAttribute('stroke', a.color);
            var sw = Math.max(a.width * scope.zoom, scope.tool === 'eraser' ? 12 : a.width * scope.zoom);
            el.setAttribute('stroke-width', sw);
            el.setAttribute('stroke-linecap', 'round');
            var scaledPath = a.data.replace(/([0-9.]+)/g, function (match) { return parseFloat(match) * scope.zoom; });
            el.setAttribute('d', scaledPath);
          } else if (a.type === 'text') {
            el = document.createElementNS('http://www.w3.org/2000/svg', 'text');
            el.setAttribute('x', a.x * scope.zoom);
            el.setAttribute('y', a.y * scope.zoom);
            el.setAttribute('fill', 'red');
            el.setAttribute('font-size', (16 * scope.zoom) + 'px');
            el.setAttribute('dominant-baseline', 'hanging');
          }

          if (el) {
            el.dataset.annoIdx = idx;
            if (scope.tool === 'eraser') {
              el.style.cursor = 'not-allowed';
              el.style.pointerEvents = 'all';
              (function (capturedIdx) {
                el.addEventListener('click', function (e) {
                  e.stopPropagation();
                  scope.$apply(function () { scope.deleteAnnotation(capturedIdx); });
                });
              })(idx);
            } else {
              el.style.pointerEvents = 'none';
            }
            if (a.type === 'text') el.textContent = a.text;
            svg.appendChild(el);
          }
        });
      }

      function renderAnnotations() {
        pages.forEach(function (p) { renderPageAnnotations(p.i, p.svg); });
      }

      // Render a single page (returns a Promise)
      function renderSinglePage(i, container, myRenderId, scrollContainer, scrollPercent) {
        return pdfDoc.getPage(i).then(function (page) {
          if (myRenderId !== currentRenderId) return;

          var viewport = page.getViewport({ scale: scope.zoom });
          var wrapper = document.createElement('div');
          wrapper.className = 'pdf-page-wrapper';
          wrapper.style.width = viewport.width + 'px';
          wrapper.style.height = viewport.height + 'px';

          var canvas = document.createElement('canvas');
          canvas.className = 'pdf-canvas';
          canvas.width = viewport.width;
          canvas.height = viewport.height;

          var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
          svg.setAttribute('class', 'annotation-layer tool-' + scope.tool);
          if (scope.tool !== 'cursor') svg.classList.add('active');
          svg.setAttribute('width', viewport.width);
          svg.setAttribute('height', viewport.height);

          wrapper.appendChild(canvas);
          wrapper.appendChild(svg);
          container.appendChild(wrapper);

          var context = canvas.getContext('2d');
          return page.render({ canvasContext: context, viewport: viewport }).promise.then(function () {
            if (myRenderId !== currentRenderId) return;
            pages.push({ i: i, page: page, wrapper: wrapper, svg: svg, viewport: viewport });
            setupDrawing(svg, i);
            renderPageAnnotations(i, svg);
            if (i === 1 || i === Math.floor(pdfDoc.numPages * scrollPercent)) {
              scrollContainer.scrollTop = scrollPercent * scrollContainer.scrollHeight;
            }
          });
        });
      }

      // Render all pages progressively (sequential Promise chain)
      function renderPages(annotationsPromise, myRenderId) {
        if (!pdfDoc) return Promise.resolve();
        if (!myRenderId) myRenderId = ++currentRenderId;

        var scrollContainer = element[0].querySelector('.pdf-viewer-scroll');
        var container = element[0].querySelector('#pdf-pages');
        var scrollPercent = scrollContainer.scrollTop / (scrollContainer.scrollHeight || 1);

        pages = [];

        if (annotationsPromise) {
          annotationsPromise.then(function (annos) {
            if (myRenderId !== currentRenderId) return;
            scope.annotations = annos;
            pages.forEach(function (p) { renderPageAnnotations(p.i, p.svg); });
          });
        }

        if (container.children.length > 0) {
          container.style.minHeight = container.offsetHeight + 'px';
        }
        container.innerHTML = '';

        // Build sequential chain: page 1, then page 2, etc.
        var chain = Promise.resolve();
        for (var i = 1; i <= pdfDoc.numPages; i++) {
          (function (pageNum) {
            chain = chain.then(function () {
              if (myRenderId !== currentRenderId) return;
              return renderSinglePage(pageNum, container, myRenderId, scrollContainer, scrollPercent);
            });
          })(i);
        }

        return chain.then(function () {
          if (myRenderId === currentRenderId) {
            container.style.minHeight = '';
            scrollContainer.scrollTop = scrollPercent * scrollContainer.scrollHeight;
          }
        });
      }

      // Start loading: fetch PDF + annotations in parallel
      function startLoading(url) {
        var myRenderId = ++currentRenderId;

        scope.annotations = [];
        pages = [];

        var container = element[0].querySelector('#pdf-pages');
        container.innerHTML = '<div style="color:white;padding:20px;text-align:center"><span class="fas fa-spinner fa-spin"></span> Loading...</div>';
        container.style.minHeight = '0px';

        var docId = getDocId();
        var annotationsPromise;
        if (docId) {
          annotationsPromise = fetchAnnotations(docId);
        } else {
          annotationsPromise = new Promise(function (resolve) {
            if (deregisterDocIdWatch) deregisterDocIdWatch();
            deregisterDocIdWatch = scope.$watch(getDocId, function (newDocId) {
              if (!newDocId || myRenderId !== currentRenderId) return;
              deregisterDocIdWatch();
              deregisterDocIdWatch = null;
              fetchAnnotations(newDocId).then(resolve);
            });
          });
        }

        pdfjsLib.getDocument(url).promise.then(function (loadedPdf) {
          if (myRenderId !== currentRenderId) return;
          pdfDoc = loadedPdf;
          return renderPages(annotationsPromise, myRenderId);
        }).catch(function (e) {
          if (myRenderId !== currentRenderId) return;
          console.error('Error loading PDF:', e);
          element.html('<div class="alert alert-danger">Error loading PDF: ' + e.message + '</div>');
        });
      }

      // Tool handling
      scope.setTool = function (tool) {
        scope.tool = tool;
        element[0].querySelectorAll('.annotation-layer').forEach(function (svg) {
          svg.className = 'annotation-layer tool-' + tool;
          if (tool === 'cursor') {
            svg.classList.remove('active');
            svg.style.cursor = 'default';
          } else if (tool === 'eraser') {
            svg.classList.add('active');
            svg.style.cursor = 'not-allowed';
          } else {
            svg.classList.add('active');
            svg.style.cursor = 'crosshair';
          }
        });
        renderAnnotations();
      };

      scope.deleteAnnotation = function (idx) {
        scope.annotations.splice(idx, 1);
        renderAnnotations();
      };

      scope.clearAllAnnotations = function () {
        if (!confirm('Clear all annotations on this document? This cannot be undone until you reload.')) return;
        scope.annotations = [];
        renderAnnotations();
      };

      scope.zoomIn = function () { scope.zoom += 0.2; renderPages(); };
      scope.zoomOut = function () { if (scope.zoom > 0.4) { scope.zoom -= 0.2; renderPages(); } };

      // ── Export helpers ──────────────────────────────────────────────────
      function buildHighResMergedCanvas(pageNum) {
        return pdfDoc.getPage(pageNum).then(function (page) {
          var EXPORT_SCALE = 2.0;
          var viewport = page.getViewport({ scale: EXPORT_SCALE });

          var canvas = document.createElement('canvas');
          canvas.width = viewport.width;
          canvas.height = viewport.height;
          var ctx = canvas.getContext('2d');

          return page.render({ canvasContext: ctx, viewport: viewport }).promise.then(function () {
            var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
            svg.setAttribute('width', viewport.width);
            svg.setAttribute('height', viewport.height);

            scope.annotations.filter(function (a) { return a.page === pageNum; }).forEach(function (a) {
              if (a.type === 'pencil' || a.type === 'highlight') {
                var el = document.createElementNS('http://www.w3.org/2000/svg', 'path');
                el.setAttribute('fill', 'none');
                el.setAttribute('stroke', a.color);
                el.setAttribute('stroke-width', a.width * EXPORT_SCALE);
                el.setAttribute('stroke-linecap', 'round');
                var scaledPath = a.data.replace(/([0-9.]+)/g, function (match) { return parseFloat(match) * EXPORT_SCALE; });
                el.setAttribute('d', scaledPath);
                svg.appendChild(el);
              } else if (a.type === 'text') {
                var el2 = document.createElementNS('http://www.w3.org/2000/svg', 'text');
                el2.setAttribute('x', a.x * EXPORT_SCALE);
                el2.setAttribute('y', a.y * EXPORT_SCALE);
                el2.setAttribute('fill', 'red');
                el2.setAttribute('font-size', (16 * EXPORT_SCALE) + 'px');
                el2.setAttribute('dominant-baseline', 'hanging');
                el2.textContent = a.text;
                svg.appendChild(el2);
              }
            });

            return new Promise(function (resolve) {
              var svgStr = new XMLSerializer().serializeToString(svg);
              var svgBlob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });
              var blobUrl = URL.createObjectURL(svgBlob);
              var img = new Image();
              img.onload = function () {
                ctx.drawImage(img, 0, 0);
                URL.revokeObjectURL(blobUrl);
                resolve(canvas);
              };
              img.onerror = function () { URL.revokeObjectURL(blobUrl); resolve(canvas); };
              img.src = blobUrl;
            });
          });
        });
      }

      function generateAnnotatedPdf() {
        var loadJsPdf = Promise.resolve();
        if (typeof window.jspdf === 'undefined') {
          loadJsPdf = new Promise(function (resolve, reject) {
            var s = document.createElement('script');
            s.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js';
            s.onload = resolve;
            s.onerror = reject;
            document.head.appendChild(s);
          });
        }
        return loadJsPdf.then(function () {
          var jsPDF = window.jspdf.jsPDF;
          var promises = [];
          for (var i = 1; i <= pdfDoc.numPages; i++) {
            promises.push(buildHighResMergedCanvas(i));
          }
          return Promise.all(promises).then(function (canvases) {
            var firstW = canvases[0].width;
            var firstH = canvases[0].height;
            var pdf = new jsPDF({
              orientation: firstW > firstH ? 'landscape' : 'portrait',
              unit: 'px',
              format: [firstW, firstH],
              hotfixes: ['px_scaling']
            });
            canvases.forEach(function (c, i) {
              if (i > 0) pdf.addPage([c.width, c.height], c.width > c.height ? 'landscape' : 'portrait');
              pdf.addImage(c.toDataURL('image/jpeg', 0.95), 'JPEG', 0, 0, c.width, c.height);
            });
            return pdf;
          });
        });
      }

      scope.exportPdf = function () {
        if (scope.exporting || !pdfDoc) return;
        scope.exporting = 'pdf';
        generateAnnotatedPdf().then(function (pdf) {
          pdf.save('annotated.pdf');
        }).catch(function (e) {
          console.error('PDF export error:', e);
          alert('Export failed: ' + e.message);
        }).then(function () {
          scope.$apply(function () { scope.exporting = null; });
        });
      };

      scope.saveAsVersion = function () {
        var docId = getDocId();
        if (scope.exporting || scope.shareId || !docId) return;
        if (!confirm('This will save a new PDF version with annotations permanently "burned in". Continue?')) return;

        scope.exporting = 'version';
        generateAnnotatedPdf().then(function (pdf) {
          var pdfBlob = pdf.output('blob');
          var fd = new FormData();
          fd.append('id', docId);
          fd.append('previousFileId', scope.fileId);
          fd.append('file', pdfBlob, 'annotated.pdf');

          return $http.put('../api/file', fd, {
            transformRequest: angular.identity,
            headers: { 'Content-Type': undefined }
          });
        }).then(function () {
          alert('New version saved successfully! The page will now reload.');
          window.location.reload();
        }).catch(function (e) {
          console.error('Save version error:', e);
          alert('Failed to save version: ' + (e.data ? e.data.message : e.message));
        }).then(function () {
          scope.$apply(function () { scope.exporting = null; });
        });
      };

      // Drawing logic
      function setupDrawing(svg, pageNum) {
        svg.onmousedown = function (e) {
          if (scope.tool === 'cursor' || scope.tool === 'text' || scope.tool === 'eraser' || scope.shareId) return;
          var rect = svg.getBoundingClientRect();
          var x = (e.clientX - rect.left) / scope.zoom;
          var y = (e.clientY - rect.top) / scope.zoom;

          isDrawing = true;
          currentPath = 'M ' + x + ' ' + y;
          currentElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
          currentElement.setAttribute('fill', 'none');
          currentElement.setAttribute('stroke', scope.tool === 'highlight' ? 'rgba(255, 255, 0, 0.4)' : 'red');
          currentElement.setAttribute('stroke-width', scope.tool === 'highlight' ? '20' : '2');
          currentElement.setAttribute('stroke-linecap', 'round');
          currentElement.setAttribute('d', currentPath);
          svg.appendChild(currentElement);
        };

        svg.onclick = function (e) {
          if (scope.tool !== 'text' || scope.shareId) return;
          var rect = svg.getBoundingClientRect();
          var x = (e.clientX - rect.left) / scope.zoom;
          var y = (e.clientY - rect.top) / scope.zoom;
          addTextInput(svg, x, y, pageNum);
        };

        svg.onmousemove = function (e) {
          if (!isDrawing || !currentElement) return;
          var rect = svg.getBoundingClientRect();
          var x = (e.clientX - rect.left) / scope.zoom;
          var y = (e.clientY - rect.top) / scope.zoom;
          currentPath += ' L ' + x + ' ' + y;
          var scaledPath = currentPath.replace(/([0-9.]+)/g, function (match) { return parseFloat(match) * scope.zoom; });
          currentElement.setAttribute('d', scaledPath);
        };

        svg.onmouseup = function () {
          if (!isDrawing) return;
          isDrawing = false;
          if (currentElement) {
            scope.annotations.push({
              type: scope.tool,
              page: pageNum,
              data: currentPath,
              color: currentElement.getAttribute('stroke'),
              width: parseFloat(currentElement.getAttribute('stroke-width')) / scope.zoom
            });
            currentElement = null;
          }
        };
      }

      function addTextInput(svg, x, y, pageNum) {
        var input = document.createElement('input');
        input.type = 'text';
        input.className = 'pdf-text-input';
        input.setAttribute('autocomplete', 'off');
        input.setAttribute('spellcheck', 'false');
        input.setAttribute('data-lpignore', 'true');
        input.setAttribute('data-1p-ignore', 'true');
        input.style.left = (x * scope.zoom) + 'px';
        input.style.top = (y * scope.zoom) + 'px';
        input.style.fontSize = (16 * scope.zoom) + 'px';
        input.style.color = 'red';
        input.style.minWidth = '120px';
        input.style.zIndex = '9999';
        input.placeholder = 'Type here, Enter to confirm';
        svg.style.pointerEvents = 'none';
        svg.parentElement.appendChild(input);
        input.focus();

        var finishInput = function () {
          svg.style.pointerEvents = '';
          if (input.value.trim()) {
            scope.annotations.push({
              type: 'text',
              page: pageNum,
              x: x,
              y: y,
              text: input.value.trim()
            });
            renderAnnotations();
          }
          if (input.parentElement) input.remove();
        };

        input.onblur = finishInput;
        input.onkeydown = function (e) {
          e.stopPropagation();
          if (e.key === 'Enter') { input.onblur = null; finishInput(); }
          else if (e.key === 'Escape') { input.onblur = null; svg.style.pointerEvents = ''; input.remove(); }
        };
      }

      // Save annotations
      scope.saveAnnotations = function () {
        var docId = getDocId();
        if (scope.shareId) return;
        if (!docId) {
          alert('Cannot save: Document ID is missing.');
          return;
        }
        scope.saving = true;
        Restangular.one('comment', docId).get().then(function (data) {
          var oldAnnos = data.comments.filter(function (c) { return c.content.indexOf('[ANNOTATION]') === 0; });
          var deleteNext = function () {
            if (oldAnnos.length > 0) {
              var c = oldAnnos.shift();
              Restangular.one('comment', c.id).remove().then(deleteNext).catch(function (err) {
                console.error('Error deleting old annotation:', err);
                alert('Failed to overwrite old annotations.');
                scope.$apply(function () { scope.saving = false; });
              });
            } else {
              var formData = 'id=' + encodeURIComponent(docId) +
                             '&content=' + encodeURIComponent('[ANNOTATION]' + JSON.stringify(scope.annotations));
              $http({
                method: 'PUT',
                url: '../api/comment',
                data: formData,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
              }).then(function () {
                console.log('Annotations saved successfully!');
                scope.saving = false;
              }, function (err) {
                console.error('Error saving annotation:', err);
                alert('Failed to save annotations.');
                scope.saving = false;
              });
            }
          };
          deleteNext();
        }).catch(function (err) {
          console.error('Error fetching comments:', err);
          alert('Failed to connect to server. Are you still logged in?');
          scope.$apply(function () { scope.saving = false; });
        });
      };

      // Watch fileId - reset and reload when switching files
      scope.$watch('fileId', function (newFileId) {
        if (!newFileId) return;
        scope.annotations = [];
        pdfDoc = null;
        pages = [];
        var url = '../api/file/' + newFileId + '/data' + (scope.shareId ? '?share=' + scope.shareId : '');
        $timeout(function () {
          startLoading(url);
        });
      });
    }
  };
});
