/**
 * Created by Gifer on 11.07.2015.
 */

"use strict";

var Service	    = require('./service.js');
//var console	    = require('console-plus');
var console	    = require('gifer-console');
var webUploader = require('multer');
var fs          = require('fs');
var _purl       = require('./mctools/other/purl').purl;
var crypto      = require('crypto');

var CRLF     = "\r\n";

var checkUploadRights = require('./mcconnect').checkUploadRights;

function sendToClient(res, data, code){
    res.statusCode = code || 200;
    res.end(JSON.stringify(data));
}

function webImage(req, res){
    var postData = '';
    // var purl     = _purl(req.url);
    // var hashFile = purl.param('hash');

    req.addListener("data", function(postDataChunk) {
        postData += postDataChunk;

        if (postData.length > MCServer.maxUploadData){
            console.err("POST data is too large. Break connection.", console.logLevel.ERROR);

            req.removeAllListeners();
        }
    });

    req.addListener("end", function() {
        var image = Service.decodeBase64Image(postData);
        var fileName = Date.now() + ".pasteImage.png";

        if (!image){
            setTimeout(function(){
                sendToClient(res, {
                    status   : 'error',
                    fileName : 'empty'
                }, 403);
            }, 10);
        } else {
            fs.writeFile(MCPathes.Uploads + fileName, image.data, function(err) {
                if (err){
                    sendToClient(res, {
                        status   : 'error',
                        fileName : fileName
                    }, 403);
                } else {
                    sendToClient(res, {
                        status   : 'server',
                        fileName : fileName
                    });
                }
            });
        }
    });
}

function webFile(req, res){
    var fileName  = "ttt";
    var purl      = _purl(req.url);
    var sid       = purl.param('sid');
    var isSert    = purl.param('issert');
    var sertFile  = purl.param('sertfile');
    var hashFile  = purl.param('hash');
    var where     = purl.param('where');
    var fSize     = req.headers['content-length'] || 0;
    var sizee     = 0;
    var checkHash = "";
    var sha1      = crypto.createHash('sha1');
    var destFilePath = isSert && sertFile ? MCPathes.Cert : (MCPathes.Uploads + (where && (where === "kanban" || where === "forum") ? where + "/" : ""));
    var skipFile  = false;

    if ((MCServer.MaxUploadFileSize && (MCServer.MaxUploadFileSize > fSize)) || MCServer.MaxUploadFileSize === 0){
        webUploader({
            dest    : destFilePath,
            inMemory: false,
            // checkFileName: function (filename){
            //     skipFile = true;
            //
            //     return false; // check filename
            // },
            rename  : function (fieldname, filename) {
                var ext = Service.ExtractFileExtension(filename);

                // console.log("UPLOADING file: " + filename);
                // console.log("UPLOADING hash: " + hashFile);

                fileName = isSert && sertFile
                    ? filename
                    : ( hashFile
                        ? hashFile + (ext ? "." + (filename === 'blob' ? 'png' : ext) : "")
                        : filename
                    )
                ;

                return  fileName;
            },
            onError: function (error) {
                var request = this;

                console.log("[webUploader uERR, " + request.remoteHostIp + "]: " + error);

                sha1 = null;

                try {
                    fs.unlink(destFilePath + fileName, function (err) {
                        if (err){
                            console.err(err.message, console.logLevel.ERROR);
                        } else {
                            console.warn('File ' + destFilePath + fileName + ' deleted', console.logLevel.WARN);
                        }
                    });
                } catch (e){}

                sendToClient(res, error, 403);
            },
            onFileUploadData: function (file, data, req, res) {
                sizee += data.length;
                if (sha1){
                    sha1.update(data);
                }
            }
        })(req, res, function(error){
            if (sha1) {
                checkHash = sha1.digest('hex');
            }

            console.log("sizee: " + sizee);

            if (error || skipFile){
                console.log("[webUploader ERR, " + req.remoteHostIp + "]: " + error);
                console.log('Upload file - ' + fileName + ' from User: ' + (sid || "regular client") + " SHA1: " + checkHash);
                console.log('SHA1 (' + hashFile + ') equals: ' + (hashFile === checkHash));

                sendToClient(res, {
                    status   : 'error'
                }, 403);
            } else {

                console.log('Upload file - ' + fileName + ' from User: ' + (sid || "regular client") + " SHA1: " + checkHash);
                console.log('SHA1 (' + hashFile + ') equals: ' + (hashFile === checkHash));

                if (!hashFile || (hashFile && hashFile === checkHash)) {
                    setTimeout(function (){
                        sendToClient(res, {
                            status   : 'server',
                            fileName : fileName
                        });
                    }, 10);
                } else {
                    try {
                        fs.unlink(destFilePath + fileName, function (err) {
                            if (err){
                                console.err(err.message, console.logLevel.ERROR);
                            } else {
                                console.warn('File ' + destFilePath + fileName + ' deleted', console.logLevel.INFO);
                                console.warn('Because sended SHA1 not equal to content SHA1 checksum', console.logLevel.INFO);
                            }
                        });
                    } catch (e){}

                    sendToClient(res, {
                        status   : 'error'
                    }, 403);
                }

                sha1 = null;
            }
        });
    } else {
        sendToClient(res, {
            status   : 'error'
        }, 403);
    }
}

function mcFile(req, res, info){
    var firstChunk     = true;
    var fd             = '';
    var fragment       = 0;
    var postData       = [];
    var postDataLength = 0;
    var secondHeader   = info[1] || 0;
    var isChunkNumber  = info[2] || 0;

    req.addListener("data", function(postDataChunk) {
        if (firstChunk){
            firstChunk = false;

            var data = ((postDataChunk.slice(0, secondHeader)).toString()).split(CRLF);

            postDataChunk = postDataChunk.slice(secondHeader, postDataChunk.length);

            fd = MCPathes.Uploads + data[0];

            if (isChunkNumber === "0"){
                try{
                    fs.unlinkSync(fd);
                } catch (e){}
            }
        }

        postData.push(postDataChunk);
        postDataLength += postDataChunk.length;

        fragment ++;

        if (postDataLength > MCServer.maxUploadData){
            console.err("POST data is too large. Break connection.", console.logLevel.ERROR);

            res.statusCode = 403;
            res.end("WTF?");

            req.removeAllListeners();

            postData = null;
        }
    });

    req.addListener("end", function() {
        if (postData && postData.length > 0){
            fs.appendFileSync(fd, Buffer.concat(postData));

            res.statusCode = 200;
            res.end("ok|" + isChunkNumber + "|" + fragment);
        }
    });
}

function uploader (req, res) {
    function isWeb(){
        // console.log('checkUploadRights(sid): ' + checkUploadRights(sid));
        // console.log('cLength: ' + cLength);
        // console.log('cLength <= MCServer.maxUploadData: ' + (cLength <= MCServer.maxUploadData));

        return sid
            && checkUploadRights(sid)
            && cLength
            && cLength <= MCServer.maxUploadData;
    }

    if (req.method === 'POST'){
        var purl    = _purl(req.url);
        var sid     = purl.param('sid');
        var cLength = req.headers['content-length'] || 0;
        var cType   = req.headers['content-type'] || "";

        if (isWeb()){
            if (cType === 'pastImage/Base64'){
                webImage(req, res);
            } else {
                webFile(req, res);
            }
        } else
        if (cType.indexOf('multipart/form-data') === 0) {
            webFile(req, res);

            console.log("FileSize: " + cLength);
        } else {
            console.warn('Rejected file from: ' + req.url, console.logLevel.INFO);

            sendToClient(res, {
                status   : 'error'
            }, 403);
        }
    }
}

exports.upload = uploader;