
const geokit = require('geokit');
const geocoder = require('offline-geocoder')({ database: 'static/db.sqlite'});

function MetaStruct() {
    this.artist = undefined;
    this.exposureProgram = undefined;
    this.exposureTime = undefined;
    this.exposureTimeStr = undefined;
    this.dateTime = undefined;
    this.fNumber = undefined;
    this.focal = undefined;
    this.lensModel = undefined;
    this.camera = undefined;
    this.software = undefined;
    this.iso = undefined;
    this.width = undefined;
    this.height = undefined;
    this.compression = undefined;
    this.gpsLocation = undefined;
    this.geoHash = undefined;
    this.geoCountry = undefined;
    this.geoAdmin = undefined;
    this.geoCity = undefined;
    this.orientation = undefined;
    this.tags = undefined;

    // Internal
    this.imException = undefined;
    this.exifParsed = false;
}

MetaStruct.prototype.setExposureProgram = function(progId) {
    if (isNaN(progId) || !progId)
        this.exposureProgram = undefined;
    else
        this.exposureProgram = [ "Manual", "Normal program", "Aperture priority", "Shutter priority",
            "Creative program", "Action program", "Portrait mode", "Landscape mode"][progId];
}

function ExifGps(lat, latRef, lon, lonRef) {
    this.lat = null;
    this.lon = null;

    if (!lat || !lon)
        return;
    if (latRef && latRef !== 'N' && lat >= 0)
        lat[0] *= -1;
    if (lonRef && lonRef !== 'E' && lon[0] >= 0)
        lon[0] *= -1;
    this.lat = lat[0] + lat[1] / 60 + lat[2]/3600;
    this.lon = lon[0] + lon[1] / 60 + lon[2]/3600;
    if (!this.lat || isNaN(this.lat) || !this.lon || isNaN(this.lon))
        this.lat = this.lon = null;
}

ExifGps.prototype.toGps = function() {
    if (this.lat === null)
        return undefined;
    return JSON.stringify([this.lat, this.lon]);
}

ExifGps.prototype.toGeoHash = function() {
    if (this.lat === null)
        return undefined;
    return geokit.hash({lat: this.lat, lng: this.lon});
}

ExifGps.prototype.toAddress = function() {
    return new Promise(async (ok, ko) => {
        if (this.lat === null)
            return ok(undefined);
        const data = await geocoder.reverse(this.lat, this.lon);
        ok({
            city: data?.name,
            admin: data?.admin1?.name,
            country: data?.country?.name
        });
    });
}

MetaStruct.prototype.setGPSInfo = async function(latitude, latitudeRef, longitude, longitudeRef) {
    let gpsData = new ExifGps(latitude, latitudeRef, longitude, longitudeRef);
    this.gpsLocation = gpsData.toGps();
    this.geoHash = gpsData.toGeoHash();
    const address = await gpsData.toAddress();
    this.geoCountry = address?.country;
    this.geoAdmin = address?.admin;
    this.geoCity = address?.city;
}

module.exports.MetaStruct = MetaStruct;

