"""Local visual QA; outputs remain on this machine. Not an accuracy benchmark
unless independently labelled reference polygons are supplied separately.
"""
import argparse
import json
import time
from pathlib import Path

import cv2
import numpy as np
import shapely

from app.pipeline import PipelineOptions, load_source, vectorize_document


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('source', type=Path)
    parser.add_argument('--output', type=Path, required=True)
    parser.add_argument('--max-side', type=int, default=5200)
    args = parser.parse_args()
    args.output.mkdir(parents=True, exist_ok=True)
    payload = args.source.read_bytes()
    started = time.perf_counter()
    result = vectorize_document(payload, args.source.name, '', 1, PipelineOptions(max_side=args.max_side))
    elapsed = time.perf_counter() - started
    polygons = [shapely.Polygon([(p['x'], p['y']) for p in r['points']]) for r in result['regions']]
    summary = {'engine': result['engine'], 'seconds': round(elapsed, 2), 'plots': len(polygons),
               'vertices': sum(len(r['points']) for r in result['regions']),
               'coverage_valid': bool(shapely.coverage_is_valid(polygons)),
               'source': result['source'], 'analysis': result['analysis']}
    print(json.dumps(summary), flush=True)
    (args.output / 'summary.json').write_text(json.dumps(summary, indent=2), encoding='utf-8')
    image, _ = load_source(payload, args.source.name, '', 1)
    for name, crop in [('overview', (0, 0, image.shape[1], image.shape[0])),
                       ('detail', (int(image.shape[1] * .40), int(image.shape[0] * .41),
                                   int(image.shape[1] * .53), int(image.shape[0] * .55)))]:
        x0, y0, x1, y1 = crop
        scale = min(1, 1800 / (x1 - x0))
        base = cv2.resize(image[y0:y1, x0:x1], (round((x1-x0)*scale), round((y1-y0)*scale)))
        fill = base.copy()
        contours = []
        palette = [(250,205,175), (185,235,190), (175,225,250), (230,185,235)]
        for index, region in enumerate(result['regions']):
            points = np.array([[(p['x'] - x0) * scale, (p['y'] - y0) * scale] for p in region['points']], np.int32)
            if points[:, 0].max() < 0 or points[:, 1].max() < 0 or points[:, 0].min() >= base.shape[1] or points[:, 1].min() >= base.shape[0]:
                continue
            cv2.fillPoly(fill, [points], palette[index % len(palette)])
            contours.append(points)
        overlay = cv2.addWeighted(fill, .25, base, .75, 0)
        cv2.polylines(overlay, contours, True, (175,85,25), 1, cv2.LINE_AA)
        cv2.imwrite(str(args.output / f'{name}.jpg'), np.concatenate((base, overlay), axis=1))


if __name__ == '__main__':
    main()
