import {setupApphierarchy,
    basicAppHierarchyCreator_WithFields} from "./specHelpers";
import {keys, filter} from "lodash/fp";
import {$} from "../src/common";
import {permission} from "../src/authApi/permissions";
import {Readable} from "readable-stream";


const getFile = () => {
    const contentString = "hello";
    var bytes = []; // char codes

    for (let i = 0; i < contentString.length; ++i) {
        const code = contentString.charCodeAt(i);    
        bytes = bytes.concat([code & 0xff, code / 256 >>> 0]);
    } 

    const s = new Readable();
    s._read = () => {
        s.push(Buffer.from(bytes));
        s.push(null);
    }; 

    return ({
        file: {relativePath:"thefile.txt", size:bytes.length},
        content: bytes,
        stream: s
    });
}



describe("recordApi > files", () => {
 
    it("upload should fail when files size does not equal stream size", async () => {
        const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
        const {file, stream, content} = getFile();
        file.size = file.size - 1;
        const record = recordApi.getNew("/customers", "customer");
        record.surname = "Ledog";
        record.profilepic = file;
        await recordApi.save(record);
        expect(recordApi.uploadFile(record.key, stream, file.relativePath)).rejects.toThrow();
    });

    it("upload should fail when record does not exist", async () => {
        const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
        const {file, stream, content} = getFile();
        const record = recordApi.getNew("/customers", "customer");
        record.surname = "Ledog";
        record.profilepic = file;
        await recordApi.save(record);
        expect(recordApi.uploadFile("does nto exist", stream, file.relativePath)).rejects.toThrow();
    });

    it("download should get an uploaded file", async () => {
        const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
        const {file, stream, content} = getFile();
        const record = recordApi.getNew("/customers", "customer");
        record.surname = "Ledog";
        record.profilepic = file;
        await recordApi.save(record);
        await recordApi.uploadFile(record.key, stream, file.relativePath);
        const downloadedStream = await recordApi.downloadFile(record.key, file.relativePath);
        const downloadedBytes = downloadedStream.read();
        for(let i=0; i<downloadedBytes.length; i++) {
            expect(downloadedBytes[i]).toEqual(content[i]);
        }
    });
    
    it("upload should fail when filename contains invalid characters", async () => {
        const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
        const {file, stream, content} = getFile();
        const record = recordApi.getNew("/customers", "customer");
        record.surname = "Ledog";
        record.profilepic = file;
        await recordApi.save(record);
        let ex;
        try {
            await recordApi.uploadFile(record.key, stream, "some:file.txt");
        } catch (e) {
            ex = e;
        }
        expect(ex).not.toBeNull();
    });


    it("upload should fail when path contains '..' ", async () => {
        const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
        const {file, stream, content} = getFile();
        const record = recordApi.getNew("/customers", "customer");
        record.surname = "Ledog";
        record.profilepic = file;
        await recordApi.save(record);
        expect(recordApi.uploadFile(record.key, stream, "../somefile.txt")).rejects.toThrow();
    });
    
});