
import ApiQuery from '../Tools/ApiQuery'
import Configuration from '../Tools/Configuration'
import Log from '../Tools/LogTools'


export default class UploadServices {

    constructor() {

        this.URL_Start = "/api/UploadFiles/StartUpload";
        this.URL_Upload = "/api/UploadFiles/UploadBlob";
        this.URL_Cansel = "/api/UploadFiles/Cansel";

        this.upload_chunk_size = Configuration.upload_chunk_size;
        this.ID = -1;

        this._ContinueDownload = false;

        this._file = null;
        this._ParentID = null;

        //Callback события
        //(number progresse)
        this.OnProggresseChange = null;
        //(number id)
        this.OnIDReceived = null;
    }


    //Считывает часть файла
    //startByte - int позиция начала чтения
    //stopByte - int позиция окончания чтения
    async _ReadBlobAsync(startByte, stopByte) {
        return new Promise(function (resolve, reject) {
            //Считываем часть файла
            let blob = this._file.slice(startByte, stopByte);

            let reader = new FileReader();
            reader.onload = function () {
                resolve(reader.result);
            };
            reader.onerror = function (event) {
                reject("js Read file error", event);
            };

            reader.readAsDataURL(blob);
        }.bind(this));
    }

    //Сообщает серверу о начале загрузки файла, получает ID загрузки
    async _StartUploadAsync() {
        return await ApiQuery(this.URL_Start, "Post",
            {
                //ID папки
                ParentID: this._ParentID,
                //Имя файла
                Name: this._file.name,
                //Размеры
                Size: this._file.size
            }).then(function (data) {
                return data;
            }.bind(this));
    }

    //Выполняет загрузка блока
    async _UploadBlobAsync(bin_data, ChunkNumb) {

        Log("UploadServices", "_UploadBlobAsync" + ChunkNumb);

        if (!this._ContinueDownload)
            return { Successe: true };


        if (bin_data != '') {
            Log("UploadServices", this.URL_Upload + ChunkNumb);

            let res;

            await ApiQuery(this.URL_Upload, "Post",
                {
                    //ID загрузки
                    ID: this.ID,
                    //Кусок файла
                    chunk: bin_data
                    //Номер куска
                    //'ChunkNumb': ChunkNumb
                }).then(function (data) {
                    res = data;
                }.bind(this));

            return res;
        }
    }


    //Инициирует загрузку файла
    //parent_id - int ID папки для загрузки
    async UploadFileAsync(file, parent_id) {

        if (this.OnProggresseChange != null)
            this.OnProggresseChange(0, 0);

        this._file = file;
        this._ParentID = parent_id;

        let start_info = await this._StartUploadAsync();
        if (!start_info.Successe) {
            throw start_info;
        }

        this._ContinueDownload = true;
        this.ID = start_info.UploadID;
        if (this.OnIDReceived != null)
            this.OnIDReceived(this.ID);

        for (let pos = 0, ChunkNumb = 0; pos < this._file.size; pos += this.upload_chunk_size, ChunkNumb++) {
            if (!this._ContinueDownload)
                return;

            let bin_data = await this._ReadBlobAsync(pos, pos + this.upload_chunk_size);
            let upload_state = await this._UploadBlobAsync(bin_data, ChunkNumb);


            if (!upload_state.Successe) {
                throw upload_state;
            }

            // Вычисляем процент отправленного
            let p = Math.round(pos * 100 / file.size);
            Log("UploadServices", 'p = ' + p);

            if (this.OnProggresseChange != null)
                this.OnProggresseChange(p, pos);
        }

        this._ContinueDownload = false;
    }

    Cansel() {
        this._ContinueDownload = false;

        //Костыль задержка, чтобы асинхронный загрузчик точно прервал работу
        //и не попытался получить доступ к ужаленному проекту загрузки
        //Возможно зависит от размера блока
        setTimeout(function () {

            ApiQuery(this.URL_Cansel, "Post",
                {
                    //ID файла
                    ID: this.ID,
                });

        }.bind(this),
            500);
    }

}
