/*
<copyright file="BGExcelImageProcessorBeforeDelete.cs" company="BansheeGz">
    Copyright (c) 2018-2024 All Rights Reserved
</copyright>
*/

using System;
using NPOI.OpenXmlFormats.Dml.Spreadsheet;
using NPOI.XSSF.UserModel;
using UnityEngine;

namespace BansheeGz.BGDatabase.Editor
{
    public class BGExcelImageProcessorBeforeExport
    {
        public void Process(BGExcelImageProcessorBeforeExportRequest request)
        {
            request.bookInfo.ForEachEntitySheet(info =>
            {
                var sheet = request.workbook.GetSheet(info.SheetName);
                if (sheet == null) return;

                var meta = request.repo.GetMeta(info.MetaId);
                if (meta == null) return;
                
                request.assetsConfig.ForEachImageField(meta, true, field =>
                {
                    var column = info.GetFieldColumn(field.Id);
                    if (column < 0) return;
                    var deleted = RemoveImages((XSSFSheet)sheet, column, rowNum => !info.GetRowId(rowNum).IsEmpty);
                    if (deleted > 0) request.logger.AppendLine("Sheet $, Field $, Removed $ images", info.SheetName, field.FullName, deleted);
                });

            });
        }

        public static int RemoveImages(XSSFSheet sheet, int column, Predicate<int> rowFilter)
        {
            var count = 0;
            var drawing = sheet.DrawingPatriarch;
            if (!(drawing is XSSFDrawing xssfDrawing)) return count;
            var shapes = xssfDrawing.GetShapes();
            foreach (var shape in shapes)
            {
                if (!(shape is XSSFPicture xssfPicture)) continue;
                var anchor = xssfPicture.GetAnchor();
                if (!(anchor is XSSFClientAnchor xssfAnchor)) continue;
                if (xssfAnchor.Col1 != column) continue;
                if (!rowFilter(xssfAnchor.Row1)) continue;
                try
                {
                    if (RemoveImage(xssfDrawing, xssfPicture, xssfAnchor)) count++;
                }
                catch (Exception)
                {
                    Debug.LogError($"Error while removing an image, sheet={sheet.SheetName}, column={column}, row={xssfAnchor.Row1}");
                    throw;
                }
            }

            return count;
        }

        private static bool RemoveImage(XSSFDrawing drawing, XSSFPicture xssfPicture, XSSFClientAnchor anchor)
        {
            var removed = false;
            //relation
            var blipFill = xssfPicture.GetCTPicture().blipFill;
            var blip = blipFill?.blip;
            //embed is relation ID
            var embed = blip?.embed;
            if (embed != null)
            {
                removed = true;
                drawing.GetPackagePart().RemoveRelationship(embed);
                var partName = drawing.GetRelationById(embed).GetPackagePart().PartName;
                drawing.GetPackagePart().Package.DeletePartRecursive(partName);
            }

            //anchor
            var picture = xssfPicture.GetCTPicture();
            var anchors = drawing.GetCTDrawing().CellAnchors;
            foreach (var anAnchor in anchors)
            {
                //is it reliable enough? probably not
                if (anAnchor.picture != picture) continue;

                switch (anAnchor)
                {
                    case CT_AbsoluteCellAnchor _: continue;
                    case CT_OneCellAnchor oneCellAnchor:
                    {
                        if (oneCellAnchor.from == null) continue;
                        if (oneCellAnchor.from.col != anchor.Col1) continue;
                        if (oneCellAnchor.from.row != anchor.Row1) continue;
                        break;
                    }
                    case CT_TwoCellAnchor twoCellAnchor:
                    {
                        if (twoCellAnchor.from == null) continue;
                        if (twoCellAnchor.from.col != anchor.Col1) continue;
                        if (twoCellAnchor.from.row != anchor.Row1) continue;
                        break;
                    }
                }

                anchors.Remove(anAnchor);
                break;
            }

            return removed;
        }
    }
}