system.directive('fulfillteezily', function () {
    return {
        controller: function ($scope, $http, Upload, $q) {
            this.__proto__ = new BaseFulfillController($scope, $http);
            const framedImageWorkerUrl = 'https://printerval.com/print-suppliers/framed-image';
            // const framedImageWorkerUrl = 'http://etsy.test/print-suppliers/framed-image';

            $scope.debug = false;
            if (user_email == 'tienanhbui0597@gmail.com') $scope.debug = true;

            $scope.profiles = {};
            $scope.teezilyCurrentOrder = {};
            $scope.teezily = {
                initialized: false,
                products: [],
                colors: [],
                sizes: []
            };

            let productTemplateIds = [];

            $scope.teezily_openFulfillForm = async function (orderOrCard) 
            {
                let order = angular.copy(orderOrCard);

                if (typeof orderOrCard.order_id != 'undefined') 
                {
                    $scope.loadingOrderInfo = true; 
                    order = await $scope.loadOrderInfo(orderOrCard.order_id, orderOrCard.locale_code);
                    $scope.loadingOrderInfo = false;

                    $scope.fulFillLocale = orderOrCard.locale_code;

                    safeApply();

                    if (!order) return toastr.error('Error! Cannot find order infomation...');

                } else {
                    if (typeof order.location != 'undefined' && order.location !== '') {
                        $scope.fulFillLocale = angular.copy(order.location);
                    } else {
                        $scope.fulFillLocale = null;
                    }
                }

                $('#modalFulfillTeezily').modal({
                    modal: true,
                    persist: true,
                    position: [30, 0],
                    autoPosition: true
                });

                if (!$scope.teezily.initialized) {
                    await initializeTeezily();
                    $scope.teezily.initialized = true;
                }

                $scope.teezilyCurrentOrder = angular.copy(order);
                $scope.getSuggestsPrinting($scope.teezilyCurrentOrder.code);
                if ($scope.teezilyCurrentOrder.attributes.customer_info) {
                    $scope.teezilyCurrentOrder.customer.phone = $scope.teezilyCurrentOrder.attributes.customer_info.phone;
                    $scope.teezilyCurrentOrder.customer.full_name = $scope.teezilyCurrentOrder.attributes.customer_info.full_name;
                }

                if ($scope.teezilyCurrentOrder.shipping_type != 'express') {
                    $scope.teezilyCurrentOrder.shipping_type = 'standard';
                }

                if ($scope.teezilyCurrentOrder.customer) {

                    if (typeof $scope.teezilyCurrentOrder.attributes.gift_info != 'undefined' && $scope.teezilyCurrentOrder.attributes.gift_info.name) {
                        $scope.teezilyCurrentOrder.customer.full_name = $scope.teezilyCurrentOrder.attributes.gift_info.name;
                        if ($scope.teezilyCurrentOrder.attributes.gift_info.phone) {
                            $scope.teezilyCurrentOrder.customer.phone = $scope.teezilyCurrentOrder.attributes.gift_info.phone;
                        }
                    }

                    $scope.teezilyCurrentOrder.customer.full_name = $scope.capitalizeFirstLetter($scope.teezilyCurrentOrder.customer.full_name);
                    if (window.user_email) {
                        $scope.teezilyCurrentOrder.customer.email = window.user_email;
                    }
                }

                // init print logistic attr
                for (let i = 0; i < $scope.teezilyCurrentOrder.items.length; i++) {
                    $scope.teezilyCurrentOrder.items[i].teezily = {
                       variants: [],
                       product: {},
                       colors: [],
                       sizes: [],

                       product_id: null,
                       color: null,
                       size: null,
                       designFiles: {}
                    };
                }

                fetchProfiles();

                $scope.checkEstimateCosts($scope.teezilyCurrentOrder, toastr);

                safeApply();
            }

            $scope.changeTeezilyProduct = async (orderItem) => 
            {
                const product = $scope.teezily.products.find((productItem) => {
                    return productItem.id == orderItem.teezily.product_id;
                });

                if (product) 
                {
                    orderItem.teezily.product = product;

                    let padding = localStorage.getItem("teezily_design_padding");
                    if (!padding) padding = 300;

                    for (let i = 0; i < product.print_positions.length; i++) {
                        const position = product.print_positions[i];
                        if (typeof orderItem.teezily.designFiles[position] == 'undefined') {
                            orderItem.teezily.designFiles[position] = {
                                padding: parseInt(padding)
                            };
                        }
                    }

                    return getVariants(orderItem);
                }
            }

            $scope.changeTeezilyColor = async (orderItem) => 
            {   
                if (!orderItem.teezily.color || !orderItem.teezily.size) return;
                
                const variant = orderItem.teezily.variants.find((variant) => {
                    return orderItem.teezily.color.toLowerCase() == variant.color.toLowerCase()
                        && orderItem.teezily.size.toLowerCase() == variant.size.toLowerCase();
                });

                orderItem.teezily.variant = variant;
                safeApply();

            }
            $scope.changeTeezilySize = $scope.changeTeezilyColor;

            $scope.teezily_uploadImages = async function (files, item, designFile) 
            {
                let supportedFilesType = ['image/png', 'image/jpg', 'image/jpeg', 'image/gif'];
                let supportedFilesExtensions = ['jpg', 'jpeg', 'png', 'gif'];

                item.teezily.uploading = true;

                if (files) {
                    try {

                        let imagesUploaded = [];
                        let imageFile = null;
                        if (files && files.length) {
                            imageFile = files[0];

                            let fileExtension = imageFile.name.split('.').pop();
                            fileExtension = fileExtension.toLowerCase();
                            if (
                                supportedFilesExtensions.includes(fileExtension) &&
                                supportedFilesType.includes(imageFile.type)
                            ) {
                                imagesUploaded = await $scope.teezily_uploads(files);
                            } else {
                                toastr.error('Error! format supported: jpg, jpeg, png, gif');
                            }
                        }

                        if (imagesUploaded.length) {
                            $scope.$applyAsync(function () {
                                let imageUrl = imagesUploaded.pop();
                                if (imageUrl) {
                                    designFile.extension = imageFile.name.split('.').pop();
                                    designFile.url = imageUrl;
                                }
                                item.teezily.uploading = false;
                            });
                        }

                    } catch (error) {
                        console.log(error);
                        toastr.error('Error upload images!');
                    }
                }
            };

            $scope.teezily_uploads = function (files) 
            {
                if (typeof googleCloudStorageBucket != 'undefined') {
                    baseFileManagerUrl = googleCloudStorageBucket;
                }
                return new Promise(function (resolve, reject) {
                    Upload.upload({
                        url: baseFileManagerUrl + '/upload',
                        data: { upload: files, type: 'design' }
                    }).then(function (resp) {
                        if (resp.data.status === 'successful') {
                            let upload = resp.data.upload;
                            resolve(upload);
                        } else {
                            reject(0);
                        }
                    }, function (resp) {
                        reject(0);
                    }, function (evt) {
                        $scope.progressPercentage = 100.0 * evt.loaded / evt.total;
                    });
                });
            };

            $scope.teezily_chooseDesign = function (design, designFile) {
                if (!design.is_design_comfirm) {
                    toastr.error('Design is not confirmed');
                    return;
                }
                if (designFile.url !== design.url) {
                    designFile.url = design.url;
                    designFile.extension = design.url.split('.').pop();
                    $scope.teezily_changeDesignUrl(designFile);
                    safeApply();
                }
            }

            $scope.teezily_changeDesignUrl = function (designFile)
            {
                console.log(designFile)
                designFile.extension = designFile.url.split('.').pop();
                designFile.designPositions = {};

                safeApply();
            }

            const orderTeezily = async () => 
            {
                safeApply();

                const printervalOrder = angular.copy($scope.teezilyCurrentOrder);

                $scope.textNotify = 'Processing design file(s)...'
                loadingButton('#btnPostTeezilyOrder');

                await processDesigns(printervalOrder.items);

                $scope.textNotify = ''
                stopLoadingButton('#btnPostTeezilyOrder');

                if (teezily_validateItem(printervalOrder.items).validated) 
                {
                    const teezilyOrderBody = buildFulfillOrderBody(printervalOrder);
                    const param = {
                        title: 'Create Order',
                        customText: 'Post order to Teezily!',
                        confirmButtonText: 'Ok',
                        cancelButtonText: 'Back'
                    };

                    swal({
                        title: param.title,
                        html: param.customText,
                        type: "warning",
                        showConfirmButton: true,
                        showCancelButton: true,
                        confirmButtonText: param.confirmButtonText,
                        cancelButtonText: param.cancelButtonText
                    }).then(async function (isConfirm) 
                    {
                        if (isConfirm.value) {
                        
                            $scope.textNotify = 'Creating Order...'
                            loadingButton('#btnPostTeezilyOrder');

                            postProfiles(printervalOrder);

                            postToTeezily(teezilyOrderBody);

                        } else {
                            console.log(teezilyOrderBody);
                        }

                    });

                } else  { // show error validate
                    document.getElementById("errorModalTeezily").style.display = "block";
                }
            }

            $scope.orderTeezily = orderTeezily;

            const processDesigns = (orderItems) => {

                const promises = [];
                
                for (let i = 0; i < orderItems.length; i++) {
                    const item = orderItems[i];
                    const designFiles = item.teezily.designFiles;

                    for (const key in designFiles) {
                        if (Object.hasOwnProperty.call(designFiles, key)) 
                        {
                            const design = designFiles[key];

                            promises.push(new Promise((resolve, reject) => {
                                if (typeof design.url != 'undefined' && design.hasPadding === true && design.padding) {
                                    getPaddingDesign(design.url, design.padding).then((paddingDesignUrl) => {
                                        if (paddingDesignUrl) {
                                            design.paddingUrl = paddingDesignUrl;
                                        }
                                        resolve();
                                    });
                                } else {
                                    resolve();
                                }
                            }));
                        }
                    }
                }

                return Promise.all(promises);
            }

            const getPaddingDesign = async (url, padding) => 
            {
                let framedImage = new URL(framedImageWorkerUrl);

                const designResolution = await getImageSize(url);

                cropParams = {
                    i: url,
                    fw: designResolution[0] + padding * 2,
                    fh: designResolution[1] + padding * 2,
                    x: -padding,
                    y: -padding,
                }

                localStorage.setItem("teezily_design_padding", padding);

                framedImage.search = new URLSearchParams(cropParams);
                framedImage = framedImage.toString();

                return new Promise(function(resolve) {

                    var xhttp = new XMLHttpRequest();
                    xhttp.onreadystatechange = function() {
                        if (this.readyState == 4 && this.status == 200) {
                            const response = JSON.parse(xhttp.responseText);
                            if (response.imageUrl) {
                                resolve(response.imageUrl);                            
                            }
                        }
                    };
                    xhttp.open("GET", framedImage, true);
                    xhttp.send();
                });
            }

            const getImageSize = (url, callback = () => {}) => {
                return new Promise((resolve, reject) => {
                    const img = new Image();
                    img.onload = function() {
                        resolve([this.width, this.height]);
                        callback(this.width, this.height);
                    };
                    img.src = url; 
                });
            }

            const loadingButton = function (selector, text = 'Processing...') {
                $(selector).attr('dt-text', $(selector).text());
                $(selector).text(text);
                $(selector).attr("disabled", true);
            }

            const stopLoadingButton = function (selector) {
                $(selector).html($(selector).attr('dt-text'));
                $(selector).attr("disabled", false);
            }

            const buildProfiles = (order) =>
            {
                const profiles = [];
                for (let i = 0; i < order.items.length; i++) 
                {
                    const item = order.items[i];
                    const options = {
                        designFiles: item.teezily.designFiles,
                        color: item.teezily.color,
                        size: item.teezily.size,
                        variant: item.teezily.variant,
                        product_id: item.teezily.product_id
                    }

                    profiles.push({
                        product_id: item.product_id,
                        is_template_product: isTemplateProduct(item.product_id),
                        product_sku_id: item.product_sku_id,
                        order_id: item.id,
                        order_item_id: item.id,
                        options,
                        type: 'teezily'
                    });
                }
                return profiles;
            }

            const isTemplateProduct = (productId) => {
                return productTemplateIds.includes(productId);
            }

            const fetchProfiles = () =>
            {
                $scope.getDesignJobOrder($scope.teezilyCurrentOrder);

                const requestObj = $scope.buildLocaleData('/print-suppliers/get-profile', {
                    type: 'teezily',
                    order_items: $scope.teezilyCurrentOrder.items
                }, $scope.fulFillLocale);

                $http.post(requestObj.url, requestObj.params).then(function(response) {
                    if (response.data.status === 'successful') {
                        $scope.profiles = {
                            profiles: response.data.profiles,
                            designs: response.data.designs
                        };
                        productTemplateIds = response.data.product_template_ids;
                        applyProfiles();
                    }
                }, function(error) {
                    toastr.error('Error load profiles!');
                });
            }

            const postProfiles = (order) => 
            {
                const profiles = buildProfiles(order);
                const errMessage = 'Error save profile. Please contact technical team.';
                const promisePostProfile = new Promise(function (resolve, reject) {
                    const requestObj = $scope.buildLocaleData('/print-suppliers/profile', profiles, $scope.fulFillLocale);
                    $http.post(requestObj.url, requestObj.params).then(function(response) {
                        if (response.data.status === "successful") {
                            resolve(response.data.data);
                        } else {
                            toastr.error(errMessage);
                            reject();
                        }
                    });
                });

                const promises = [promisePostProfile];

                return Promise.all(promises);
            }

            const applyProfiles = async () => 
            {
                $scope.teezilyCurrentOrder.items.forEach(async printOrderItem => {

                    let profile = null;
                    let designs;

                    if (!printOrderItem.teezily.profile) {
                        printOrderItem.teezily.profile = {};
                    }

                    if (isTemplateProduct(printOrderItem.product_id)) {
                        profile = $scope.profiles.profiles.find(function (item) {
                            return parseInt(item.product_id) === parseInt(printOrderItem.product_id) && item.is_template_product;
                        });
                        designs = $scope.findDesign(printOrderItem, true, $scope.profiles.designs);
                    } else {
                        profile = $scope.profiles.profiles.find(function (item) {
                            return parseInt(item.product_sku_id) === parseInt(printOrderItem.product_sku_id) && !item.is_template_product;
                        });
                        designs =  $scope.findDesign(printOrderItem, false, $scope.profiles.designs);
                    }

                    printOrderItem.teezily.patternDesigns = [];
                    if(designs && designs.length) {
                        printOrderItem.teezily.patternDesigns = designs;
                        setTimeout(() => {
                            $('[data-magnify=gallery]').magnify({
                                zIndex: 10000
                            });
                        }, 500);
                    }

                    if(profile) 
                    {
                        const profileOptions = profile.options;

                        if (typeof profileOptions.designFiles != 'undefined') {
                            printOrderItem.teezily.designFiles = profileOptions.designFiles;
                        }

                        if (typeof profileOptions.product_id != 'undefined') 
                        {
                            printOrderItem.teezily.product_id = String(profileOptions.product_id);

                            if (typeof profileOptions.color != 'undefined') {
                                printOrderItem.teezily.color = profileOptions.color;
                            }
    
                            if (typeof profileOptions.size != 'undefined') {
                                printOrderItem.teezily.size = profileOptions.size;
                            }
                        }

                        await $scope.changeTeezilyProduct(printOrderItem);
                        await $scope.changeTeezilyColor(printOrderItem);
                    }

                });
            }

            const postToTeezily = (teezilyOrderBody) => 
            {
                toastr.options.positionClass = "toast-bottom-left";

                if ($scope.debug) {
                    toastr.success('Successfully');
                    $('#modalFulfillTeezily').modal('hide');
                    stopLoadingButton('#btnPostTeezilyOrder');
                    return;
                }

                const requestObj = $scope.buildLocaleData('/print-suppliers/teezily/api?method=POST&end_point=v2/orders ', teezilyOrderBody, $scope.fulFillLocale);

                $http.post(requestObj.url, { params: requestObj.params }).then(function (response)
                {
                    if (response.data.id) {
                        toastr.success('Successfully');
                        $('#modalFulfillTeezily').modal('hide');
                    } else {
                        toastr.error('Has an Error! Please contact technical team.  | ' + JSON.stringify(response.data));
                    }

                    /* const mapItemPrintProvider = {};
                    const printervalOrder = angular.copy($scope.TeezilyCurrentOrder);
                    for (let index = 0; index < printervalOrder.items.length; index++) {
                        const item = printervalOrder.items[index];
                        mapItemPrintProvider[item.id] = 'Teezily';
                    }
                    afterFulfillAction(TeezilyOrder, {mapItemPrintProvider}); */

                    stopLoadingButton('#btnPostTeezilyOrder');
                    
                }).catch(function(error) {
                    toastr.error('Has an Error! Please contact technical team. | ' + JSON.stringify(error));
                    $('#modalFulfillTeezily').modal('hide');
                    stopLoadingButton('#btnPostTeezilyOrder');
                });
            }

            const buildFulfillOrderBody = (currentOrder) => 
            {
                const fullName = currentOrder.customer.full_name;
                const partsName = fullName.split(' ');
                const lengthName = partsName.length;

                const lastName = partsName.pop();
                let firstName = partsName.join(' ');

                if (lengthName < 2) {
                    firstName = lastName;
                }

                let city = ' ';
                if (currentOrder.city_name) {
                    city = currentOrder.city_name;
                }

                let region = ' ';
                if(currentOrder.state_name){
                    region = currentOrder.state_name;
                }

                const lineItems = getLineItems(currentOrder);

                let orderReferenceId = "API" + "_" + currentOrder.code;

                const orderSchema = {
                    "external_reference": orderReferenceId + '_' + new Date().getTime().toString().substr(-4),
                    "email": currentOrder.customer.email,
                    "address": {
                        "first_name": firstName,
                        "last_name": lastName,
                        "street1": currentOrder.delivery_address,
                        "street2": currentOrder.optional_address,
                        "city": city,
                        "state": region,
                        "postcode": currentOrder.zip_code,
                        "country_code": currentOrder.country.iso,
                        "phone": currentOrder.customer.phone
                    },
                    "line_items": lineItems                
                };

                return orderSchema;
            }

            const getLineItems = (currentOrder) => 
            {
                const lineItems = [];

                for (let i = 0; i < currentOrder.items.length; i++) {
                    const item = currentOrder.items[i];

                    const designs = [];
                    for (const key in item.teezily.designFiles) {
                        if (Object.hasOwnProperty.call(item.teezily.designFiles, key)) {
                            const design = item.teezily.designFiles[key];
                            if (design.url) {
                                
                                let designUrl = design.url;
                                if (design.hasPadding === true && typeof design.paddingUrl != 'undefined') {
                                    designUrl = design.paddingUrl;
                                }

                                designs.push({
                                    "key": key,
                                    "url": designUrl
                                });
                            }
                        }
                    }

                    lineItems.push({
                        "external_reference": item.id,
                        "variant_reference": item.teezily.variant.reference,
                        "quantity": item.quantity,
                        "designs": designs
                    });
                }

                return lineItems;
            }

            const teezily_validateItem = (items) =>
            {
                let validated = true;
                let messages = {};

                for (let i = 0; i < items.length; i++) {
                    const itemData = items[i];
                    messages[itemData.product_sku_id] = [];

                    if (!itemData.teezily.variant) {
                        validated = false;
                        messages[itemData.product_sku_id].push(itemData.name + ' || Missing Print Logistic SKU.');
                    }

                    const artworks = itemData.teezily.designFiles;
                    let hasDesign = false;
                    for (const key in artworks) {
                        if (Object.hasOwnProperty.call(artworks, key)) {
                            const artwork = artworks[key];
                            if (artwork.url) {
                                hasDesign = true;
                                break;
                            }
                        }
                    }
                    if (!hasDesign) {
                        validated = false;
                        messages[itemData.product_sku_id].push(itemData.name + ' || Missing Design.');
                    }

                }

                $scope.teezily.messages = messages;

                safeApply();

                return {
                    validated,
                    messages
                };
            }


            const initializeTeezily = async function () {
                return new Promise((resolve) => {
                    Promise.all([getProducts()]).then(() => {
                        resolve();
                    });
                });
            }

            const getProducts = () => 
            {
                const requestObj = $scope.buildLocaleData('/print-suppliers/teezily/products', {}, $scope.fulFillLocale);
                return $http.get(requestObj.url, {
                    params: requestObj.params
                }).then((response) => {
                    if (response.data) {
                        $scope.teezily.products = response.data;
                    }
                });
            }

            const getVariants = (orderItem) =>
            {
                orderItem.teezily.loading = true;
                const requestObj = $scope.buildLocaleData('/print-suppliers/teezily/variants', {
                    product_id: orderItem.teezily.product_id
                }, $scope.fulFillLocale);

                return $http.get(requestObj.url, {
                    params: requestObj.params
                }).then((response) => {
                    if (response.data) {
                        orderItem.teezily.variants = response.data.variants;
                        orderItem.teezily.colors = response.data.colors;
                        orderItem.teezily.sizes = response.data.sizes;
                        orderItem.teezily.loading = false;
                        safeApply();
                    }
                });
            }

            function safeApply() {
                if ($scope.$root.$$phase !== '$apply' && $scope.$root.$$phase !== '$digest') {
                    $scope.$apply();
                }
            }
            
            // initializeTeezily();
        }
    };
});
