/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.xssf.binary;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.ss.util.CellAddress;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeUtil;
import org.apache.poi.util.Internal;
import org.apache.poi.xssf.usermodel.XSSFRelation;

/**
 * @since 3.16-beta3
 */
@Internal
public class XSSFBHyperlinksTable {

    private static final SparseBitSet RECORDS = new SparseBitSet();


    static {
        RECORDS.set(XSSFBRecordType.BrtHLink.getId());
    }


    private final List<XSSFHyperlinkRecord> hyperlinkRecords = new ArrayList<>();

    //cache the relId to hyperlink url from the sheet's .rels
    private Map<String, String> relIdToHyperlink = new HashMap<>();

    public XSSFBHyperlinksTable(PackagePart sheetPart) throws IOException {
        //load the urls from the sheet .rels
        loadUrlsFromSheetRels(sheetPart);
        //now load the hyperlinks from the bottom of the sheet
        HyperlinkSheetScraper scraper = new HyperlinkSheetScraper(sheetPart.getInputStream());
        scraper.parse();
    }

    /**
     *
     * @return a map of the hyperlinks. The key is the top left cell address in their CellRange
     */
    public Map<CellAddress, List<XSSFHyperlinkRecord>> getHyperLinks() {
        Map<CellAddress, List<XSSFHyperlinkRecord>> hyperlinkMap =
                new TreeMap<>(new TopLeftCellAddressComparator());
        for (XSSFHyperlinkRecord hyperlinkRecord : hyperlinkRecords) {
            CellAddress cellAddress = new CellAddress(hyperlinkRecord.getCellRangeAddress().getFirstRow(),
                    hyperlinkRecord.getCellRangeAddress().getFirstColumn());
            List<XSSFHyperlinkRecord> list = hyperlinkMap.get(cellAddress);
            if (list == null) {
                list = new ArrayList<>();
            }
            list.add(hyperlinkRecord);
            hyperlinkMap.put(cellAddress, list);
        }
        return hyperlinkMap;
    }


    /**
     *
     * @param cellAddress cell address to find
     * @return null if not a hyperlink
     */
    public List<XSSFHyperlinkRecord> findHyperlinkRecord(CellAddress cellAddress) {
        List<XSSFHyperlinkRecord> overlapping = null;
        CellRangeAddress targetCellRangeAddress = new CellRangeAddress(cellAddress.getRow(),
                cellAddress.getRow(),
                cellAddress.getColumn(),
                cellAddress.getColumn());
        for (XSSFHyperlinkRecord record : hyperlinkRecords) {
            if (CellRangeUtil.intersect(targetCellRangeAddress, record.getCellRangeAddress()) != CellRangeUtil.NO_INTERSECTION) {
                if (overlapping == null) {
                    overlapping = new ArrayList<>();
                }
                overlapping.add(record);
            }
        }
        return overlapping;
    }

    private void loadUrlsFromSheetRels(PackagePart sheetPart) {
        try {
            for (PackageRelationship rel : sheetPart.getRelationshipsByType(XSSFRelation.SHEET_HYPERLINKS.getRelation())) {
                relIdToHyperlink.put(rel.getId(), rel.getTargetURI().toString());
            }
        } catch (InvalidFormatException e) {
            //swallow
        }
    }

    private class HyperlinkSheetScraper extends XSSFBParser {

        private XSSFBCellRange hyperlinkCellRange = new XSSFBCellRange();
        private final StringBuilder xlWideStringBuffer = new StringBuilder();

        HyperlinkSheetScraper(InputStream is) {
            super(is, RECORDS);
        }

        @Override
        public void handleRecord(int recordType, byte[] data) throws XSSFBParseException {
            if (recordType != XSSFBRecordType.BrtHLink.getId()) {
                return;
            }
            int offset = 0;

            hyperlinkCellRange = XSSFBCellRange.parse(data, offset, hyperlinkCellRange);
            offset += XSSFBCellRange.length;
            xlWideStringBuffer.setLength(0);
            offset += XSSFBUtils.readXLNullableWideString(data, offset, xlWideStringBuffer);
            String relId = xlWideStringBuffer.toString();
            xlWideStringBuffer.setLength(0);
            offset += XSSFBUtils.readXLWideString(data, offset, xlWideStringBuffer);
            String location = xlWideStringBuffer.toString();
            xlWideStringBuffer.setLength(0);
            offset += XSSFBUtils.readXLWideString(data, offset, xlWideStringBuffer);
            String toolTip = xlWideStringBuffer.toString();
            xlWideStringBuffer.setLength(0);
            /*offset +=*/ XSSFBUtils.readXLWideString(data, offset, xlWideStringBuffer);
            String display = xlWideStringBuffer.toString();
            CellRangeAddress cellRangeAddress = new CellRangeAddress(hyperlinkCellRange.firstRow, hyperlinkCellRange.lastRow, hyperlinkCellRange.firstCol, hyperlinkCellRange.lastCol);

            String url = relIdToHyperlink.get(relId);
            if (location.length() == 0) {
                location = url;
            }

            hyperlinkRecords.add(
                    new XSSFHyperlinkRecord(cellRangeAddress, relId, location, toolTip, display)
            );
        }
    }

    private static class TopLeftCellAddressComparator implements Comparator<CellAddress>, Serializable {
        private static final long serialVersionUID = 1L;
        
        @Override
        public int compare(CellAddress o1, CellAddress o2) {
            if (o1.getRow() < o2.getRow()) {
                return -1;
            } else if (o1.getRow() > o2.getRow()) {
                return 1;
            }
            if (o1.getColumn() < o2.getColumn()) {
                return -1;
            } else if (o1.getColumn() > o2.getColumn()) {
                return 1;
            }
            return 0;
        }
    }

}
