import { PouchDB, TypeSpec } from '../services/db.js';
import { blobToArrayBuffer, deepAssign } from '../utils/conversion.js';
import { backgroundTask } from '../utils/event.js'
import { FileType } from './file.js';
import { error } from '../services/console.js';


class ImageSpec extends TypeSpec {
    static async upload(blob) {
        const f = await FileType.upload(blob, false);
        const doc = await ImageType.getOrCreate({
            digest: f.digest,
            originalDate: f.lastModified,
            importing: true,
            width: 0,
            height: 0,
            sizes: {
                full: FileType.getURL(f)
            }
        });
        processImportables(doc);
        return doc;
    };

    static getUniqueID(doc) {
        return doc.digest.substr(0, 16);
    }

    static getSequence(doc) {
        return new Date(doc.originalDate).getTime();
    }

    async delete(cascade=true) {
        if (cascade) {
            new Set(Object.keys(this.sizes)).forEach(async key => {
                const f = await FileType.getDocFromURL(this.sizes[key])
                f.delete();
            });
        }
        return await this.update({_deleted: true});
    }
    //
    // static validate(doc) {
    //     // TODO actually validate perhaps against a JSON schema
    //
    //     const schema = {
    //         originalDate: t.REQUIRED_DATE,
    //         digest: t.REQUIRED_STRING,
    //         width: t.INTEGER,
    //         height: t.INTEGER,
    //         sizes: {
    //             type: 'object',
    //             properties: {
    //                 full: t.REQUIRED_STRING,
    //                 thumbnail: t.STRING,
    //             }
    //         },
    //         orientation: t.INTEGER,
    //         make: t.STRING,
    //         model: t.STRING,
    //         flash: t.BOOLEAN,
    //         iso: t.INTEGER,
    //         gps: {
    //             type: 'object',
    //             properties: {
    //                 latitude: t.NUMBER,
    //                 longitude: t.NUMBER,
    //                 altitude: t.NUMBER,
    //                 heading: t.NUMBER,
    //             }
    //         },
    //         tags: {
    //             type: "object",
    //             additionalProperties: t.BOOLEAN
    //         }
    //     };
    // }
}

const processImportables = backgroundTask(async function _processImportables(image) {
    const { _id, _rev, sizes, digest } = image;
    const imageData = await FileType.getFromURL(image.sizes.full);

    const img = new Image();
    const imageProps = await new Promise(resolve => {
        img.onload = () => {
            resolve({width: img.width, height: img.height});
            URL.revokeObjectURL(img.src);
        }
        img.src = URL.createObjectURL(imageData);
    });


    if (new Set(['image/jpg', 'image/jpeg']).has(imageData.type)) {
        const ExifParser = await import('exif-parser');
        const buffer = await blobToArrayBuffer(imageData);

        try {
            const exifData = ExifParser.create(buffer).parse();
            const { tags } = exifData;
            const originalDate = new Date(
                tags.DateTimeOriginal
                ? (new Date(tags.DateTimeOriginal * 1000)).toISOString()
                : image.originalDate
            ).toISOString();

            deepAssign(imageProps, {
                originalDate,
                width,
                height,
                orientation: tags.Orientation,
                digest,
                make: tags.Make,
                model: tags.Model,
                flash: !!tags.Flash,
                iso: tags.ISO,
                sizes,
                gps: {
                    latitude: tags.GPSLatitude,
                    longitude: tags.GPSLongitude,
                    altitude: tags.GPSAltitude,
                    heading: tags.GPSImgDirection,
                }
            });
        } catch(e) {
            error(e);
        }
    }

    delete image.importing;
    image.update(imageProps);

    const module = await import('../context/generateThumbnails');
    module.generateThumbnailForImage(image);
}, false);

export const ImageType = PouchDB.registerType("Image", ImageSpec);

ImageType.find({importing: true})
    .then(results => results.forEach(processImportables));

@@ -2519,22 +2519,16 @@
 FromURL(
-image.
 sizes.fu
@@ -3006,26 +3006,8 @@
 );%0A%0A
-        try %7B%0A    
     
@@ -3066,28 +3066,24 @@
 ();%0A        
-    
 const %7B tags
@@ -3097,20 +3097,16 @@
 ifData;%0A
-    
         
@@ -3144,28 +3144,24 @@
             
-    
 tags.DateTim
@@ -3170,20 +3170,16 @@
 riginal%0A
-    
         
@@ -3251,20 +3251,16 @@
         
-    
 : image.
@@ -3280,20 +3280,16 @@
         
- 
-   
 ).toISOS
@@ -3294,28 +3294,24 @@
 OString();%0A%0A
-    
         deep
@@ -3335,36 +3335,32 @@
 , %7B%0A            
-    
 originalDate,%0A  
@@ -3361,59 +3361,8 @@
 te,%0A
-                width,%0A                height,%0A    
     
@@ -3416,20 +3416,16 @@
     
-  
-  
 digest,%0A
     
@@ -3412,36 +3412,32 @@
         digest,%0A
-    
             make
@@ -3457,28 +3457,24 @@
             
-    
 model: tags.
@@ -3488,28 +3488,24 @@
             
-   
- 
 flash: !!tag
@@ -3521,28 +3521,24 @@
             
-    
 iso: tags.IS
@@ -3556,23 +3556,15 @@
     
-  
-  
 sizes,%0A
-    
     
@@ -3586,36 +3586,32 @@
                 
-    
 latitude: tags.G
@@ -3630,36 +3630,32 @@
                 
-   
- 
 longitude: tags.
@@ -3676,36 +3676,32 @@
                 
-    
 altitude: tags.G
@@ -3720,36 +3720,32 @@
                 
- 
-   
 heading: tags.GP
@@ -3763,36 +3763,32 @@
 on,%0A            
-    
 %7D%0A            %7D)
@@ -3785,68 +3785,11 @@
     
- 
-   %7D);%0A        %7D catch(e) %7B%0A            error(e);%0A        %7D
+%7D);
 %0A   

Clean up image import a bit