package exif

import (
	"log"

	"github.com/pkg/errors"
	"gorm.io/gorm"

	"github.com/kjeldgaard/go-exiftool"
	"github.com/photoview/photoview/api/graphql/models"
)

type exifParser interface {
	ParseExif(media *models.Media) (*models.MediaEXIF, error)
}

// SaveEXIF scans the media file for exif metadata and saves it in the database if found
func SaveEXIF(tx *gorm.DB, media *models.Media) (*models.MediaEXIF, error) {

	log.Printf("Scanning for EXIF: %s", media.Path)

	{
		// Check if EXIF data already exists
		if media.ExifID != nil {

			var exif models.MediaEXIF
			if err := tx.First(&exif, media.ExifID).Error; err != nil {
				return nil, errors.Wrap(err, "get EXIF for media from database")
			}

			return &exif, nil
		}
	}

	// Decide between internal or external Exif parser
	et, err := exiftool.NewExiftool()
	et.Close()
	var parser exifParser
	if err != nil {
		parser = &internalExifParser{}
	} else {
		parser = &externalExifParser{}
	}


	exif, err := parser.ParseExif(media)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse exif data")
	}

	if exif == nil {
		return nil, nil
	}

	// Add EXIF to database and link to media
	if err := tx.Model(&media).Association("Exif").Replace(exif); err != nil {
		return nil, errors.Wrap(err, "save media exif to database")
	}

	if exif.DateShot != nil && !exif.DateShot.Equal(media.DateShot) {
		media.DateShot = *exif.DateShot
		if err := tx.Save(media).Error; err != nil {
			return nil, errors.Wrap(err, "update media date_shot")
		}
	}

	return exif, nil
}
