const app = window.require('photoshop').app
const batchPlay = require('photoshop').action.batchPlay
const { executeAsModal } = require('photoshop').core
// const export_png = require('./export_png')

// const { layerToSelection } = require('./helper')

const storage = require('uxp').storage
const fs = storage.localFileSystem

async function createSolidLayer(r, g, b) {
    console.warn('this function is deprecated')
    await executeAsModal(async () => {
        const result = await batchPlay(
            [
                {
                    _obj: 'make',
                    _target: [
                        {
                            _ref: 'contentLayer',
                        },
                    ],
                    using: {
                        _obj: 'contentLayer',
                        type: {
                            _obj: 'solidColorLayer',
                            color: {
                                _obj: 'RGBColor',
                                red: r,
                                grain: g,
                                blue: b,
                            },
                        },
                    },
                    _options: {
                        dialogOptions: 'dontDisplay',
                    },
                },
            ],
            {
                synchronousExecution: true,
                modalBehavior: 'execute',
            }
        )
    })
}

async function makeGroupCommand() {
    const result = await batchPlay(
        [
            {
                _obj: 'make',
                _target: [
                    {
                        _ref: 'layerSection',
                    },
                ],
                layerSectionStart: 405,
                layerSectionEnd: 406,
                name: 'Group 16',
                _options: {
                    dialogOptions: 'dontDisplay',
                },
            },
        ],
        {
            synchronousExecution: true,
            modalBehavior: 'execute',
        }
    )

    console.log('makeGroupCommand: ', result)

    return result
}
async function createEmptyGroup(name = 'New Group') {
    let groupLayer
    await executeAsModal(async () => {
        await makeGroupCommand()
        groupLayer = app.activeDocument.activeLayers[0]
        groupLayer.name = name
    })
    console.log('groupLayer:', groupLayer)
    return groupLayer
}

async function moveToGroupCommand(to_index, layerIDs) {
    const batchPlay = require('photoshop').action.batchPlay
    console.log('to_index:', to_index)
    console.log('layerIDs:', layerIDs)

    const result = await batchPlay(
        [
            {
                _obj: 'move',
                _target: [
                    {
                        _ref: 'layer',
                        _enum: 'ordinal',
                        _value: 'targetEnum',
                    },
                ],
                to: {
                    _ref: 'layer',
                    _index: to_index,
                },
                adjustment: false,
                version: 5,
                layerID: layerIDs,
                _options: {
                    dialogOptions: 'dontDisplay',
                },
            },
        ],
        {
            synchronousExecution: true,
            modalBehavior: 'execute',
        }
    )
}
function MoveToGroupExe(toIndex, layerIDs) {
    try {
        executeAsModal(async () => {
            await moveToGroupCommand(toIndex, layerIDs)
        })
    } catch (e) {
        console.warn('executeCommand error:', e)
    }
}

async function getIndexCommand(layer_id) {
    const idx = batchPlay(
        [
            {
                _obj: 'get',
                _target: [
                    {
                        _property: 'itemIndex',
                    },
                    {
                        _ref: 'layer',
                        // _name: 'myGroup'
                        _id: layer_id,
                    },
                ],
                _options: {
                    dialogOptions: 'dontDisplay',
                },
            },
        ],
        { synchronousExecution: true }
    )[0]['itemIndex']
    console.log('index:', idx)
    return idx
}

async function getLayerIndex(layer_id) {
    const { executeAsModal } = require('photoshop').core
    try {
        let index
        await executeAsModal(async () => {
            index = await getIndexCommand(layer_id)
            console.log('getIndex: ', index)
        })
        return index
    } catch (e) {
        console.warn('getIndex error:', e)
    }
}

async function unselectActiveLayers() {
    const layers = await app.activeDocument.activeLayers
    for (layer of layers) {
        layer.selected = false
    }
}
async function unselectActiveLayersExe() {
    await executeAsModal(async () => {
        await unselectActiveLayers()
    })
}
async function selectLayers(layers) {
    await unselectActiveLayers()
    for (layer of layers) {
        try {
            if (layer) {
                const is_visible = layer.visible // don't change the visibility when selecting the layer
                layer.selected = true
                layer.visible = is_visible
            }
        } catch (e) {
            console.warn(e)
        }
    }
}

async function setVisibleExe(layer, is_visible) {
    try {
        await executeAsModal(async () => {
            layer.visible = is_visible
        })
    } catch (e) {
        console.warn(e)
    }
}
async function selectLayersExe(layers) {
    await executeAsModal(async () => {
        await selectLayers(layers)
    })
}
async function selectGroup(layer) {
    await unselectActiveLayers()
    layer.parent.selected = true
}
async function collapseGroup(layer) {
    await selectGroup(layer)
    await app.activeDocument.activeLayers[0].merge()
}

async function createMaskCommand() {
    const batchPlay = require('photoshop').action.batchPlay

    const result = await batchPlay(
        [
            {
                _obj: 'make',
                new: {
                    _class: 'channel',
                },
                at: {
                    _ref: 'channel',
                    _enum: 'channel',
                    _value: 'mask',
                },
                using: {
                    _enum: 'userMaskEnabled',
                    _value: 'revealSelection',
                },
                _options: {
                    dialogOptions: 'dontDisplay',
                },
            },
        ],
        {
            synchronousExecution: true,
            modalBehavior: 'execute',
        }
    )
}

async function createMaskExe() {
    const { executeAsModal } = require('photoshop').core
    await executeAsModal(createMaskCommand)
}

//unselect the rectangular marquee selection area
async function unSelectMarqueeCommand() {
    const batchPlay = require('photoshop').action.batchPlay

    const result = await batchPlay(
        [
            {
                _obj: 'set',
                _target: [
                    {
                        _ref: 'channel',
                        _property: 'selection',
                    },
                ],
                to: {
                    _enum: 'ordinal',
                    _value: 'none',
                },
                _options: {
                    dialogOptions: 'dontDisplay',
                },
            },
        ],
        {
            synchronousExecution: true,
            modalBehavior: 'execute',
        }
    )

    return result
}
async function unSelectMarqueeExe() {
    try {
        await executeAsModal(unSelectMarqueeCommand)
    } catch (e) {
        console.warn(e)
    }
}

//REFACTOR: move to selection.js
async function selectMarqueeRectangularToolExe() {
    async function selectMarqueeRectangularToolCommand() {
        const result = await batchPlay(
            [
                {
                    _obj: 'select',
                    _target: [
                        {
                            _ref: 'marqueeRectTool',
                        },
                    ],
                    _options: {
                        dialogOptions: 'dontDisplay',
                    },
                },
            ],
            {
                synchronousExecution: true,
                modalBehavior: 'execute',
            }
        )
        return result
    }
    await executeAsModal(async () => {
        await selectMarqueeRectangularToolCommand()
    })
}

async function promptForMarqueeTool() {
    console.warn('promptForMarqueeTool is deprecated use Notification class')(
        async () => {
            const r1 = await dialog_box.prompt(
                'Please Select a Rectangular Area',
                'You Forgot to select a Rectangular Area',
                ['Cancel', 'Rectangular Marquee']
            )
            if ((r1 || 'Rectangular Marquee') !== 'Rectangular Marquee') {
                /* cancelled or No */
                console.log('cancel')
            } else {
                /* Yes */
                console.log('Rectangular Marquee')
                selectMarqueeRectangularToolExe()
            }
        }
    )()
}

async function selectLayerChannelCommand() {
    //   const result = await batchPlay(
    //     [
    //       {
    //         _obj: 'set',
    //         _target: [
    //           {
    //             _ref: 'channel',
    //             _property: 'selection'
    //           }
    //         ],
    //         to: {
    //           _ref: [
    //             {
    //               _ref: 'channel',
    //               _enum: 'channel',
    //               _value: 'transparencyEnum'
    //             },
    //             {
    //               _ref: 'layer',
    //               _name: 'Group 5'
    //             }
    //           ]
    //         },
    //         _options: {
    //           dialogOptions: 'dontDisplay'
    //         }
    //       }
    //     ],
    //     {
    //       synchronousExecution: false,
    //       modalBehavior: 'execute'
    //     }
    //   )
    const batchPlay = require('photoshop').action.batchPlay

    const result = await batchPlay(
        [
            {
                _obj: 'set',
                _target: [
                    {
                        _ref: 'channel',
                        _property: 'selection',
                    },
                ],
                to: {
                    _ref: 'channel',
                    _enum: 'channel',
                    _value: 'transparencyEnum',
                },
                _options: {
                    dialogOptions: 'dontDisplay',
                },
            },
        ],
        {
            synchronousExecution: true,
            modalBehavior: 'execute',
        }
    )
}

async function getSelectionInfoCommand() {
    // console.warn('getSelectionInfoCommand is deprecated use SelectionInfoDesc')
    const result = await batchPlay(
        [
            {
                _obj: 'get',
                _target: [
                    {
                        _property: 'selection',
                    },
                    {
                        _ref: 'document',
                        _id: app.activeDocument._id,
                    },
                ],
                _options: {
                    dialogOptions: 'dontDisplay',
                },
            },
        ],
        {
            synchronousExecution: true,
            modalBehavior: 'execute',
        }
    )

    return result
}

function isSelectionValid(selection) {
    // console.warn(
    //     'isSelectionValid is deprecated use selection.isSelectionValid instead'
    // )
    if (
        selection && // check if the selection is defined
        selection.hasOwnProperty('left') &&
        selection.hasOwnProperty('right') &&
        selection.hasOwnProperty('top') &&
        selection.hasOwnProperty('bottom')
    ) {
        return true
    }

    return false
}

async function getSelectionInfoExe() {
    // console.log('getSelectionInfo was called')
    // console.warn(
    //     'getSelectionInfoExe is deprecated use selection.getSelectionInfoExe instead'
    // )
    try {
        const selection = (await executeAsModal(getSelectionInfoCommand))[0]
            .selection

        if (isSelectionValid(selection)) {
            let selection_info = {
                left: selection.left._value,
                right: selection.right._value,
                bottom: selection.bottom._value,
                top: selection.top._value,
                height: selection.bottom._value - selection.top._value,
                width: selection.right._value - selection.left._value,
            }
            // console.dir({selection_info})
            return selection_info
        }
    } catch (e) {
        console.warn('selection info error', e)
    }
}

async function reSelectMarqueeCommand(selectionInfo) {
    const result = await batchPlay(
        [
            {
                _obj: 'set',
                _target: [
                    {
                        _ref: 'channel',
                        _property: 'selection',
                    },
                ],
                to: {
                    _obj: 'rectangle',
                    top: {
                        _unit: 'pixelsUnit',
                        _value: selectionInfo.top,
                    },
                    left: {
                        _unit: 'pixelsUnit',
                        _value: selectionInfo.left,
                    },
                    bottom: {
                        _unit: 'pixelsUnit',
                        _value: selectionInfo.bottom,
                    },
                    right: {
                        _unit: 'pixelsUnit',
                        _value: selectionInfo.right,
                    },
                },
                _options: {
                    dialogOptions: 'dontDisplay',
                },
            },
        ],
        {
            synchronousExecution: true,
            modalBehavior: 'execute',
        }
    )
}
async function reSelectMarqueeExe(selectionInfo) {
    try {
        if (isSelectionValid(selectionInfo)) {
            //only try to reactivate the selection area if it is valid
            await executeAsModal(async () => {
                await reSelectMarqueeCommand(selectionInfo)
            })
        }
    } catch (e) {
        console.warn(e)
    }
}

async function snapshot_layer() {
    let psAction = require('photoshop').action
    // const ids = (await app.activeDocument.activeLayers).map(layer => layer.id)
    const ids = await app.activeDocument.layers.map((layer) => layer.id)
    let command = [
        // Select All Layers current layer
        {
            _obj: 'selectAllLayers',
            _target: [
                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
            ],
        },
        // Duplicate current layer
        // {"ID":[459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513],"_obj":"duplicate","_target":[{"_enum":"ordinal","_ref":"layer","_value":"targetEnum"}],"version":5},
        {
            ID: ids,
            _obj: 'duplicate',
            _target: [
                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
            ],
            // version: 5
        },

        // Merge Layers
        { _obj: 'mergeLayersNew' },
        // Make
        {
            _obj: 'make',
            at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },
            new: { _class: 'channel' },
            using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },
        },
        // Set Selection
        {
            _obj: 'set',
            _target: [{ _property: 'selection', _ref: 'channel' }],
            to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },
        },
    ]
    const result = await psAction.batchPlay(command, {
        synchronousExecution: true,
        modalBehavior: 'execute',
    })
    console.log('snapshot_layer: result: ', result)
    return result
}
async function snapshot_layer_new() {
    //similar to snapshot_layer() but fixes the problem with smart effects

    let psAction = require('photoshop').action

    const ids = await app.activeDocument.layers.map((layer) => layer.id)
    const selection_info = await getSelectionInfoExe()

    let create_snapshot_layer_command = [
        // Select All Layers current layer
        {
            _obj: 'selectAllLayers',
            _target: [
                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
            ],
        },
        // Duplicate current layer

        {
            ID: ids,
            _obj: 'duplicate',
            _target: [
                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
            ],
            // version: 5
        },

        // Merge Layers
        { _obj: 'mergeLayersNew' },
    ]
    const result = await psAction.batchPlay(create_snapshot_layer_command, {
        synchronousExecution: true,
        modalBehavior: 'execute',
    })
    await reSelectMarqueeExe(selection_info) //reselect the selection area for the mask
    //make a mask of the selection area
    const make_mask_command = [
        // Make
        {
            _obj: 'make',
            at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },
            new: { _class: 'channel' },
            using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },
        },
        // // Set Selection
        // {
        //     _obj: 'set',
        //     _target: [{ _property: 'selection', _ref: 'channel' }],
        //     to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },
        // },
    ]
    const result_2 = await psAction.batchPlay(make_mask_command, {
        synchronousExecution: true,
        modalBehavior: 'execute',
    })
    await reSelectMarqueeExe(selection_info) //reselect the selection area again so we don't break other functionality

    console.log('snapshot_layer: result: ', result)
    return result
}

async function snapshot_layerExe() {
    try {
        await executeAsModal(
            async () => {
                await snapshot_layer_new()
            },
            {
                commandName: 'Action Commands',
            }
        )
    } catch (e) {
        console.error(e)
    }
}

async function snapshot_layer_no_slide() {
    let psAction = require('photoshop').action
    // const ids = (await app.activeDocument.activeLayers).map(layer => layer.id)
    const ids = await app.activeDocument.layers.map((layer) => layer.id)
    let command = [
        // Select All Layers current layer
        {
            _obj: 'selectAllLayers',
            _target: [
                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
            ],
        },
        // Duplicate current layer
        // {"ID":[459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513],"_obj":"duplicate","_target":[{"_enum":"ordinal","_ref":"layer","_value":"targetEnum"}],"version":5},
        {
            ID: ids,
            _obj: 'duplicate',
            _target: [
                { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
            ],
            // version: 5
        },

        // // Merge Layers
        // { _obj: 'mergeLayersNew' },
        // // Make
        // {
        //     _obj: 'make',
        //     at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },
        //     new: { _class: 'channel' },
        //     using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },
        // },
        // // Set Selection
        // {
        //     _obj: 'set',
        //     _target: [{ _property: 'selection', _ref: 'channel' }],
        //     to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },
        // },
    ]
    const result = await psAction.batchPlay(command, {
        synchronousExecution: true,
        modalBehavior: 'execute',
    })
    console.log('snapshot_layer: result: ', result)
    return result
}

async function snapshot_layer_no_slide_Exe() {
    try {
        await executeAsModal(
            async () => {
                await snapshot_layer_no_slide()
            },
            {
                commandName: 'Action Commands',
            }
        )
    } catch (e) {
        console.error(e)
    }
}

// await runModalFunction();

async function fillAndGroup() {
    let result
    let psAction = require('photoshop').action

    // let newCommand =[
    //   // snapshotLayer

    //   // makeGroupCommand

    //   // Make fill layer
    //   {"_obj":"make","_target":[{"_ref":"contentLayer"}],"using":{"_obj":"contentLayer","type":{"_obj":"solidColorLayer","color":{"_obj":"RGBColor","blue":255.0,"grain":255.0,"red":255.0}}}},

    // ]

    let command = [
        // Make fill layer
        {
            _obj: 'make',
            _target: [{ _ref: 'contentLayer' }],
            using: {
                _obj: 'contentLayer',
                type: {
                    _obj: 'solidColorLayer',
                    color: {
                        _obj: 'RGBColor',
                        blue: 255.0,
                        grain: 255.0,
                        red: 255.0,
                    },
                },
            },
        },
        // Move current layer
        // {"_obj":"move","_target":[{"_enum":"ordinal","_ref":"layer","_value":"targetEnum"}],"adjustment":false,"layerID":[17],"to":{"_index":7,"_ref":"layer"},"version":5},
        // Select layer “Layer 4 copy”
        // {"_obj":"select","_target":[{"_name":"Layer 4 copy","_ref":"layer"}],"layerID":[17,15],"makeVisible":false,"selectionModifier":{"_enum":"selectionModifierType","_value":"addToSelectionContinuous"}},
        // Make Group
        // {"_obj":"make","_target":[{"_ref":"layerSection"}],"from":{"_enum":"ordinal","_ref":"layer","_value":"targetEnum"},"layerSectionEnd":19,"layerSectionStart":18,"name":"Group 1"}
    ]
    const snapshotLayer = await app.activeDocument.activeLayers[0]
    await makeGroupCommand()
    const groupLayer = app.activeDocument.activeLayers[0]
    result = await psAction.batchPlay(command, {})
    const fillLayer = app.activeDocument.activeLayers[0]
    snapshotLayer.moveAbove(fillLayer)
    // await app.activeDocument.activeLayers[0].moveAbove()
    // const layerIDs = []
    // const to_index = await getIndexCommand(groupLayer.id)
    // await moveToGroupCommand(to_index, layerIDs)
}

async function fillAndGroupExe() {
    await require('photoshop').core.executeAsModal(fillAndGroup, {
        commandName: 'Action Commands',
    })
}
async function fastSnapshot() {
    await snapshot_layerExe()
    await fillAndGroupExe()
}

function layerToFileName(layer, session_id) {
    file_name = `${layer.name}_${layer.id}_${session_id}`
    return file_name
}
function layerNameToFileName(layer_name, layer_id, session_id) {
    file_name = `${layer_name}_${layer_id}_${session_id}`
    return file_name
}

async function silentSetInitImage(layer, session_id) {
    try {
        const html_manip = require('./utility/html_manip')
        const io = require('./utility/io')
        // const layer = await app.activeDocument.activeLayers[0]
        const old_name = layer.name

        // image_name = await app.activeDocument.activeLayers[0].name

        //convert layer name to a file name
        let image_name = layerNameToFileName(old_name, layer.id, session_id)
        image_name = `${image_name}.png`

        //the width and height of the exported image
        const width = html_manip.getWidth()
        const height = html_manip.getHeight()

        //get the selection from the canvas as base64 png, make sure to resize to the width and height slider
        const selectionInfo = g_generation_session.selectionInfo
        // const base64_image = await io.IO.getSelectionFromCanvasAsBase64Silent(
        //     selectionInfo,
        //     true,
        //     width,
        //     height
        // )

        const use_silent_mode = html_manip.getUseSilentMode()
        // if (use_silent_mode) {
        //     base64_image = await io.IO.getSelectionFromCanvasAsBase64Silent(
        //         selectionInfo,
        //         true,
        //         width,
        //         height
        //     )
        // } else {
        //     base64_image = await io.IO.getSelectionFromCanvasAsBase64NonSilent(
        //         layer,

        //         image_name,
        //         width,
        //         height
        //     )
        // }
        const base64_image =
            await io.IO.getSelectionFromCanvasAsBase64Interface(
                width,
                height,
                layer,
                selectionInfo,
                true,
                use_silent_mode,
                image_name
            )
        //save base64 as file in the init_images directory
        const init_entry = await getInitImagesDir()
        await io.IO.base64PngToPngFile(base64_image, init_entry, image_name)

        g_init_image_name = image_name
        console.log(image_name)

        const path = `${g_init_images_dir}/${image_name}`

        //store the base64 init image and also set it as the active/latest init image
        g_generation_session.base64initImages[path] = base64_image
        g_generation_session.activeBase64InitImage = base64_image

        const init_src = base64ToSrc(g_generation_session.activeBase64InitImage)
        html_manip.setInitImageSrc(init_src)

        return (image_info = { name: image_name, base64: base64_image })
    } catch (e) {
        console.error(`psapi.js silentSetInitImage error:, ${e}`)
    }
}
async function silentSetInitImageMask(layer, session_id) {
    try {
        const html_manip = require('./utility/html_manip')

        // const layer = await app.activeDocument.activeLayers[0]
        const old_name = layer.name

        image_name = layerNameToFileName(old_name, layer.id, session_id)
        image_name = `${image_name}.png`
        const width = html_manip.getWidth()
        const height = html_manip.getHeight()

        //get the selection from the canvas as base64 png, make sure to resize to the width and height slider
        const selectionInfo = g_generation_session.selectionInfo

        const use_silent_mode = html_manip.getUseSilentMode()

        const base64_image =
            await io.IO.getSelectionFromCanvasAsBase64Interface(
                width,
                height,
                layer,
                selectionInfo,
                true,
                use_silent_mode,
                image_name
            )

        //save base64 as file in the init_images directory
        const init_entry = await getInitImagesDir()
        await io.IO.base64PngToPngFile(base64_image, init_entry, image_name)

        g_init_image_mask_name = image_name // this is the name we will send to the server

        console.log(image_name)

        const path = `${g_init_images_dir}/${image_name}`
        g_generation_session.base64maskImage[path] = base64_image
        g_generation_session.activeBase64MaskImage = base64_image

        const mask_src = base64ToSrc(g_generation_session.activeBase64MaskImage)
        html_manip.setInitImageMaskSrc(mask_src)
        return (image_info = { name: image_name, base64: base64_image })
    } catch (e) {
        console.error(`psapi.js setInitImageMask error: `, e)
    }
}
async function setInitImage(layer, session_id) {
    try {
        const html_manip = require('./utility/html_manip')
        // const layer = await app.activeDocument.activeLayers[0]
        const old_name = layer.name

        // image_name = await app.activeDocument.activeLayers[0].name

        //convert layer name to a file name
        let image_name = layerNameToFileName(old_name, layer.id, session_id)
        image_name = `${image_name}.png`

        //the width and height of the exported image
        const width = html_manip.getWidth()
        const height = html_manip.getHeight()
        const image_buffer = await newExportPng(
            layer,
            image_name,
            width,
            height
        )
        const base64_image = _arrayBufferToBase64(image_buffer) //convert the buffer to base64
        //send the base64 to the server to save the file in the desired directory
        await sdapi.requestSavePng(base64_image, image_name)

        g_init_image_name = image_name
        console.log(image_name)

        const image_src = await sdapi.getInitImage(g_init_image_name)
        let ini_image_element = document.getElementById('init_image')
        ini_image_element.src = image_src
        const path = `${g_init_images_dir}/${image_name}`

        g_generation_session.base64initImages[path] = base64_image
        g_generation_session.activeBase64InitImage =
            g_generation_session.base64initImages[path]

        const init_src = base64ToSrc(g_generation_session.activeBase64InitImage)
        html_manip.setInitImageSrc(init_src)

        return (image_info = { name: image_name, base64: base64_image })
    } catch (e) {
        console.error(`psapi.js setInitImage error:, ${e}`)
    }
}
async function setInitImageMask(layer, session_id) {
    try {
        const html_manip = require('./utility/html_manip')

        // const layer = await app.activeDocument.activeLayers[0]
        const old_name = layer.name

        //get the active layer name
        // image_name = await app.activeDocument.activeLayers[0].name
        // image_name = layerNameToFileName(old_name,layer.id,random_session_id)
        image_name = layerNameToFileName(old_name, layer.id, session_id)
        image_name = `${image_name}.png`
        const width = html_manip.getWidth()
        const height = html_manip.getHeight()
        image_buffer = await newExportPng(layer, image_name, width, height)
        g_init_image_mask_name = image_name // this is the name we will send to the server
        // g_init_mask_layer = layer
        // g_mask_related_layers = {}

        console.log(image_name)
        base64_image = _arrayBufferToBase64(image_buffer) //convert the buffer to base64
        //send the base64 to the server to save the file in the desired directory
        await sdapi.requestSavePng(base64_image, image_name)

        const image_src = await sdapi.getInitImage(g_init_image_mask_name) // we should replace this with getInitImagePath which return path to local disk
        const ini_image_mask_element =
            document.getElementById('init_image_mask')
        ini_image_mask_element.src = image_src
        ini_image_mask_element.dataset.layer_id = layer.id

        const path = `${g_init_images_dir}/${image_name}`
        g_generation_session.base64maskImage[path] = base64_image
        g_generation_session.activeBase64MaskImage =
            g_generation_session.base64maskImage[path]
        //create viewer init image obj
        {
        }
        // return image_name
        const mask_src = base64ToSrc(g_generation_session.activeBase64MaskImage)
        html_manip.setInitImageMaskSrc(mask_src)
        return (image_info = { name: image_name, base64: base64_image })
    } catch (e) {
        console.error(`psapi.js setInitImageMask error: `, e)
    }
}

// remove the generated mask related layers from the canvas and "layers" panel

// async function cleanSnapAndFill(layers){
//   // we can delete this function and use cleanLayers() instead
//   //delete init image group
//   //delete init image (snapshot layer)
//   //delete fill layer

//   for (layer of layers){
//     try{

//       await executeAsModal(async ()=>{await layer.delete()})
//     }catch(e){
//       console.warn("cleanSnapAndFill, issue deleting a layer",e)
//     }
//   }
// return []
// }

async function cleanLayers(layers) {
    // g_init_image_related_layers = {}
    // g_mask_related_layers = {}
    // await loadViewerImages()// we should move loadViewerImages to a new file viewer.js
    console.log('cleanLayers() -> layers:', layers)
    for (layer of layers) {
        try {
            if (layer_util.Layer.doesLayerExist(layer)) {
                await executeAsModal(async () => {
                    await layer.delete()
                })
            }
        } catch (e) {
            console.warn(
                'warning attempting to a delete layer,layer.name: ',
                layer.name,
                layer,
                e
            )
            continue
        }
    }
    return []
}

// async function cleanLayersOutpaint(layers){
//   //delete group mask layer
//   //delete mask layer
//   //delete group init image layer
//   //delete init image layer (snapshot layer)
//   //delete fill layer

//   for (layer of layers){
//     try {
//       await executeAsModal(async ()=>{await layer.delete()})}
//       catch(e){
//         console.warn("warning attempting to a delete layer: ",e)
//       }
//   }

// return []
// }
// async function cleanLayersInpaint(layers){
//   //delete group mask layer
//   //delete white mask layer
//   //delete the black fill layer
//   //delete init image layer (snapshot layer)

//   for (layer of layers){
//     await executeAsModal(async ()=>{await layer.delete()})
//   }

// return []
// }
async function createClippingMaskExe() {
    const batchPlay = require('photoshop').action.batchPlay

    async function createClippingMaskCommand() {
        const result = await batchPlay(
            [
                {
                    _obj: 'make',
                    new: {
                        _class: 'channel',
                    },
                    at: {
                        _ref: 'channel',
                        _enum: 'channel',
                        _value: 'mask',
                    },
                    using: {
                        _enum: 'userMaskEnabled',
                        _value: 'revealSelection',
                    },
                    _options: {
                        dialogOptions: 'dontDisplay',
                    },
                },
            ],
            {
                synchronousExecution: true,
                modalBehavior: 'execute',
            }
        )
    }

    await executeAsModal(async () => {
        await createClippingMaskCommand()
    })
}
//REFACTOR: delete and replace with getSelectionInfoExe()
async function checkIfSelectionAreaIsActive() {
    try {
        let isSelectionAreaValid = await getSelectionInfoExe()
        return isSelectionAreaValid
    } catch (e) {
        console.warn(e)
    }
}
async function saveUniqueDocumentIdExe(new_id) {
    const batchPlay = require('photoshop').action.batchPlay

    async function saveUniqueDocumentIdCommand() {
        const batchPlay = require('photoshop').action.batchPlay

        const result = await batchPlay(
            [
                {
                    _obj: 'set',
                    _target: [
                        {
                            _ref: 'property',
                            _property: 'fileInfo',
                        },
                        {
                            _ref: 'document',
                            _enum: 'ordinal',
                            _value: 'targetEnum',
                        },
                    ],
                    to: {
                        _obj: 'fileInfo',
                        caption: new_id,
                        keywords: [new_id],
                    },
                    _options: {
                        dialogOptions: 'dontDisplay',
                    },
                },
            ],
            {
                synchronousExecution: true,
                modalBehavior: 'execute',
            }
        )
    }

    await executeAsModal(async () => {
        await saveUniqueDocumentIdCommand()
    })
}

async function readUniqueDocumentIdExe() {
    const batchPlay = require('photoshop').action.batchPlay

    async function readUniqueDocumentIdCommand() {
        const batchPlay = require('photoshop').action.batchPlay

        const result = await batchPlay(
            [
                {
                    _obj: 'get',
                    _target: [
                        {
                            _ref: 'property',
                            _property: 'fileInfo',
                        },
                        {
                            _ref: 'document',
                            _enum: 'ordinal',
                            _value: 'targetEnum',
                        },
                    ],
                    // to: {
                    //   _obj: 'fileInfo',
                    //   caption: new_id,
                    //   keywords: [new_id]
                    // },
                    _options: {
                        dialogOptions: 'dontDisplay',
                    },
                },
            ],
            {
                synchronousExecution: true,
                modalBehavior: 'execute',
            }
        )
        console.log('readUniqueDocumentIdCommand: result ', result)
        return result
    }

    let uniqueDocumentId = ''
    try {
        await executeAsModal(async () => {
            uniqueDocumentId = (await readUniqueDocumentIdCommand())[0].fileInfo
                .caption
            if (typeof uniqueDocumentId === 'string') {
                uniqueDocumentId = uniqueDocumentId.trim()
            }
        })
    } catch (e) {
        console.warn('readUniqueDocumentIdExe: ', e)
        uniqueDocumentId = ''
    }

    return uniqueDocumentId
}

const readPng = async (image_name) => {
    //it will save the document then read it. store it in memory
    // image_name = 'test.png'
    try {
        let img_buffer
        await executeAsModal(
            async (control) => {
                const folder = await fs.getTemporaryFolder()
                // const pluginFolder = await fs.getPluginFolder()

                // let init_images_dir = await pluginFolder.getEntry(
                //     './server/python_server/init_images'
                // )

                const file = await folder.createFile(image_name, {
                    overwrite: true,
                })

                const currentDocument = app.activeDocument
                await currentDocument.saveAs.png(
                    file,
                    // {
                    //   compression: 6,
                    // },
                    null,
                    true
                )

                const arrayBuffer = await file.read({ format: formats.binary })
                // console.log(arrayBuffer, 'arrayBuffer') ;
                img_buffer = arrayBuffer
            },

            { commandName: 'readPng' }
        )

        return img_buffer
    } catch (e) {
        console.warn(e)
    }
}

async function selectCanvasCommand() {
    // const result = await batchPlay(
    // [
    //    {
    //       _obj: "historyStateChanged",
    //       documentID: 1044,
    //       ID: 1058,
    //       name: "Select Canvas",
    //       hasEnglish: true,
    //       itemIndex: 7,
    //       commandID: 1017,
    //       _options: {
    //          dialogOptions: "dontDisplay"
    //       }
    //    }
    // ],{
    //    synchronousExecution: true,
    //    modalBehavior: "execute"
    // });

    const result = await batchPlay(
        [
            {
                _obj: 'set',
                _target: [
                    {
                        _ref: 'channel',
                        _property: 'selection',
                    },
                ],
                to: {
                    _enum: 'ordinal',
                    _value: 'allEnum',
                },
                _options: {
                    dialogOptions: 'dontDisplay',
                },
            },
        ],
        {
            synchronousExecution: true,
            modalBehavior: 'execute',
        }
    )

    return result
}
async function selectCanvasExe() {
    await executeAsModal(
        async () => {
            await selectCanvasCommand()
        },
        { commandName: 'selectCanvasExe' }
    )
}
async function newExportPng(layer, image_name, width, height) {
    //store layers we want to export in variables
    // let layerToExports =
    // create new document
    // duplicate the layers to the new documnet
    //select the layer channel selectLayerChannelCommand
    //document.crop
    //export using readPng()

    try {
        //get the active layers
        // const layersToExport = app.activeDocument.activeLayers

        //create new document
        // let exportDoc = await executeAsModal(app.documents.add)
        let exportDoc
        const makeDoc = async () => {
            let exportDoc = await app.documents.add({
                width: width,
                height: height,
                resolution: await app.activeDocument.resolution,
                mode: 'RGBColorMode',
                fill: 'transparent',
            })
        }
        let image_buffer
        await executeAsModal(
            async () => {
                // await app.documents.add()
                await makeDoc()
                exportDoc = app.activeDocument

                console.log('exportDoc.id: ', exportDoc.id)
                // for (layer of layersToExport) {

                console.log(layer.id)
                const dupLayer = await layer.duplicate(exportDoc)
                await selectLayers([dupLayer])
                // await selectLayerChannelCommand()
                await selectCanvasExe()
                const canvas_selection_info = await getSelectionInfoExe()
                await layerToSelection(canvas_selection_info)
                // const selection_info = await getSelectionInfoExe()
                // await exportDoc.crop(selection_info)
                // export_image_name = `${layer.name}.png`
                image_buffer = await readPng(image_name)
                await exportDoc.closeWithoutSaving()
            },
            { commandName: 'NewExportPng' }
        )
        return image_buffer
        // }
    } catch (e) {
        console.error(`newExportPng error: ,${e}`)
    }
}

async function tempExportPng(layer, image_name, width, height) {
    //store layers we want to export in variables
    // let layerToExports =
    // create new document
    // duplicate the layers to the new documnet
    //select the layer channel selectLayerChannelCommand
    //document.crop
    //export using readPng()

    try {
        //get the active layers
        // const layersToExport = app.activeDocument.activeLayers

        //create new document
        // let exportDoc = await executeAsModal(app.documents.add)
        let exportDoc
        const makeDoc = async () => {
            let exportDoc = await app.documents.add({
                width: width,
                height: height,
                resolution: await app.activeDocument.resolution,
                mode: 'RGBColorMode',
                fill: 'transparent',
            })
        }
        await executeAsModal(
            async () => {
                // await app.documents.add()
                await makeDoc()
                exportDoc = app.activeDocument

                console.log('exportDoc.id: ', exportDoc.id)
                // for (layer of layersToExport) {

                console.log(layer.id)
                const dupLayer = await layer.duplicate(exportDoc)
                await selectLayers([dupLayer])
                // await selectLayerChannelCommand()
                await selectCanvasExe()
                const canvas_selection_info = await getSelectionInfoExe()
                await layerToSelection(canvas_selection_info)
                // const selection_info = await getSelectionInfoExe()
                // await exportDoc.crop(selection_info)
                // export_image_name = `${layer.name}.png`
                await readPng(image_name)
                await exportDoc.closeWithoutSaving()
            },
            { commandName: 'tempExportPng' }
        )
        // }
    } catch (e) {
        console.error(`newExportPng error: ,${e}`)
    }
}
async function mergeVisibleCommand() {
    const result = await batchPlay(
        [
            {
                _obj: 'mergeVisible',
                duplicate: true,
                _isCommand: true,
                // "_options": {
                //   // "dialogOptions": "dontDisplay"
                // }
            },
        ],
        {
            synchronousExecution: true,
            modalBehavior: 'execute',
        }
    )

    return result
}

async function mergeVisibleExe() {
    await executeAsModal(async () => {
        await mergeVisibleCommand()
    })
}

async function layerToSelection(selection_info) {
    //store active layer for later

    try {
        //Store selection info
        //unSelect
        //move layer
        //scale layer
        //Select from selection info
        // let selection_info = await getSelectionInfo()

        console.log('selection_info:', selection_info)

        console.log('unSelect')

        function getLayerSize(layer) {
            console.log('layer.bounds:')
            console.dir(layer.bounds)
            const bounds = layer.bounds
            const height = bounds.bottom - bounds.top
            const width = bounds.right - bounds.left
            return {
                height: height,
                width: width,
                left: bounds.left,
                right: bounds.right,
                top: bounds.top,
                bottom: bounds.bottom,
            }
        }
        //scale layer
        async function scaleLayer(layer, selection_info) {
            console.log('scaleLayer got called')
            // const activeLayer = getActiveLayer()
            // const activeLayer = await app.activeDocument.activeLayers[0]

            let layer_info = getLayerSize(layer)
            scale_x_ratio = (selection_info.width / layer_info.width) * 100
            scale_y_ratio = (selection_info.height / layer_info.height) * 100
            console.log('scale_x_y_ratio:', scale_x_ratio, scale_y_ratio)
            await layer.scale(scale_x_ratio, scale_y_ratio)
        }

        async function moveLayerExe(layerToMove, selection_info) {
            let layer_info = getLayerSize(layerToMove)
            top_dist = layer_info.top - selection_info.top
            left_dist = layer_info.left - selection_info.left
            await layerToMove.translate(-left_dist, -top_dist)
        }
        // const activeLayer = await getActiveLayer()

        //store all active layers
        const activeLayers = await app.activeDocument.activeLayers
        await unSelectMarqueeExe()
        // await executeAsModal(unSelect,  {'commandName': 'unSelect'})
        // await executeAsModal(scaleLayer,  {'commandName': 'scaleLayer'})

        await executeAsModal(
            async () => {
                for (let layer of activeLayers) {
                    await selectLayers([layer]) // make sure only one layer is selected
                    await scaleLayer(layer, selection_info) //scale to selection size
                    await moveLayerExe(layer, selection_info) //move to selection
                }
            },
            { commandName: 'moveLayerExe' }
        )

        // await reselect(selection_info)
    } catch (e) {
        console.warn(e)
    }
}
function executeCommandExe(commandFunc) {
    try {
        ;(async () => {
            await executeAsModal(async () => {
                await commandFunc()
            })
        })()
    } catch (e) {
        console.warn(e)
    }
}
async function executeDescExe(Desc) {
    try {
        await executeAsModal(async () => {
            const result = await batchPlay([Desc], {
                synchronousExecution: true,
                modalBehavior: 'execute',
            })
            console.log(result)
        })
    } catch (e) {
        console.warn(e)
    }
}
module.exports = {
    createSolidLayer,
    createEmptyGroup,
    getLayerIndex,
    collapseGroup,
    moveToGroupCommand,
    MoveToGroupExe,
    selectLayers,
    selectLayersExe,
    unselectActiveLayers,
    unselectActiveLayersExe,
    createMaskExe,
    getSelectionInfoExe,
    unSelectMarqueeCommand,
    unSelectMarqueeExe,
    reSelectMarqueeExe,
    selectLayerChannelCommand,
    snapshot_layer,
    snapshot_layerExe,
    fillAndGroupExe,
    fastSnapshot,
    setInitImage,
    setInitImageMask,

    layerToFileName,
    layerNameToFileName,
    // cleanLayersOutpaint,
    // cleanLayersInpaint,
    // cleanSnapAndFill,
    cleanLayers,
    createClippingMaskExe,
    checkIfSelectionAreaIsActive,
    selectMarqueeRectangularToolExe,
    promptForMarqueeTool,
    saveUniqueDocumentIdExe,
    readUniqueDocumentIdExe,
    newExportPng,
    mergeVisibleExe,
    selectCanvasExe,
    layerToSelection,
    isSelectionValid,
    snapshot_layer_no_slide_Exe,
    setVisibleExe,
    silentSetInitImage,
    silentSetInitImageMask,
    executeCommandExe,
    executeDescExe,
}