/**
 * @since Last modified: 2024-09-10 11:20:41
 * @function getContent
 * @description Get data in synchronization or asynchronous manner.
 * @param {object} options  - Get data in synchronization or asynchronous manner.
 * @param {object} options.content  - Data source,types contain:string,HTMLElement,function.
 * @param {'text'|'html'|'fn'|'iframe'|'video'|'audio'|'image'|'async'|'form'} [options.contType='html']  - Data type.
 * @param {'post'|'get'} [options.ajaxType='post']  - Ajax type.
 * @param {object|string} [options.contData={}]  -Parameters passed when obtaining data.
 * @param {getEl} [options.parent=document.body] - The parent node of the node selector.
 * @param {*} [options.ins] - The instance of using the content.
 * @param {fn_cb_get_content} [options.cb] - Execute a function after getting content.
 * @returns {*} Return a async function.Get the content through "then".
 * @see {@link https://codepen.io/axui/pen/poGqNYp|demo @ codepen}
 * @example
 * ax.getContent({content:'#demo'});
 * <!--return async function,result is HTML of #demo-->
 * ax.getContent({content:'https://www.xxx.com/page.html#demo',type:'async');
 * <!--return async function,result is HTML from #demo of a page-->
 * ax.getContent({content:'https://www.xxx.com/demo.jpg',contType:'image');
 * <!--return async function,result is a picture element-->
 */
'use strict';
import { T_el, T_fn, T_null, T_obj } from '../../../types/ax';
import { T_getcontent } from '../../../types/utils';
import ax from '../ax';
import config from '../global/config';
import prefix from '../global/prefix';
import alias from '../global/alias';
import ajax from './ajax';
import createEl from './createEl';
import deepClone from './deepClone';
import getDataType from './getDataType';
import getEl from './getEl';
import renderTpl from './renderTpl';
import treeTools from './treeTools';
import valToArr from './valToArr';
const getContent = async function (this: any, opts: T_getcontent) {
    let dataType = getDataType(opts.content),
        getListArr = (data: any) => {
            let el = getEl(data, opts.parent) || createEl('div', {}, data),
                nodeName = el.nodeName,
                target, result;
            if (el) {
                if (['SELECT', 'DATALIST', 'UL', 'OL'].includes(nodeName)) {
                    target = el;
                } else if (nodeName === 'TEMPLATE') {
                    target = ((el as HTMLTemplateElement).content.cloneNode(true) as HTMLElement).querySelector('ul,ol,select,datalist');
                } else {
                    target = (el as HTMLElement).querySelector('ul,ol,select,datalist');
                }
            }
            if (target) {
                let tgtName = target.nodeName;
                result = (['SELECT', 'DATALIST',].includes(tgtName)) ? treeTools.fromSelect(target) :
                    (['UL', 'OL'].includes(tgtName)) ? treeTools.fromUl(target) : [];
            } else {
                result = [];
            }
            return result;
        },
        getIframe = (src: string) => {
            let dft = { src },
                iframe = createEl('iframe', Object.assign(dft, opts.contData)),
                media = createEl('div', { ref: 'media' }, iframe);
            return createEl('div', { class: `${prefix}box-iframe` }, media);
        },
        getImage = (src: string) => {
            let dft = { src },
                image = createEl('img', Object.assign(dft, opts.contData)),
                media = createEl('div', { ref: 'media' }, image);
            return createEl('div', { class: `${prefix}box-image` }, media);
        },
        getVideo = (src: string) => {
            let dft = { src, controls: 'controls' },
                video = createEl('video', Object.assign(dft, opts.contData)),
                media = createEl('div', { ref: 'media' }, video);
            return createEl('div', { class: `${prefix}box-video` }, media);
        },
        getAudio = (src: string) => {
            let dft = { src, controls: 'controls' },
                audio = createEl('audio', Object.assign(dft, opts.contData)),
                media = createEl('div', { ref: 'media' }, audio);
            return createEl('div', { class: `${prefix}box-audio` }, media);
        },
        getMedias = (type: 'iframe' | 'audio' | 'video' | 'image') => {
            let map = {
                iframe: getIframe,
                audio: getAudio,
                video: getVideo,
                image: getImage,
            },
                vals = valToArr(opts.content, opts.hyphen || config.splitHyphen).map((k: any) => k.trim()), arr = [];
            for (let k of vals) {
                arr.push(map[type](k));
            }
            return arr;
        },
        getAsync = async (url: string) => {
            let data,
                options = Object.assign({
                    url,
                    data: opts.contData,
                    success: (resp: any) => {
                        data = resp.content;
                    },
                    cb: (resp: any) => {
                        opts.request && opts.request(resp);
                    }
                }, opts.ajax);
            await ajax.call(this, options);
            return data;
        },
        getAsyncs = async () => {
            let vals = valToArr(opts.content, opts.hyphen || config.splitHyphen), arr: any[] = [];
            for (let k of vals) {
                await getAsync(k).then((resp) => {
                    arr.push(resp);
                });
            }
            return arr;
        },
        result: any;
    if (dataType === 'Number') {
        result = opts.content + '';
    } else if (dataType === 'String') {
        opts.content = opts.content.trim();
        if (opts.contType === 'text') {
            result = opts.content;
        } else if (opts.contType === 'html') {
            result = getEl(opts.content, opts.parent) ? (getEl(opts.content, opts.parent) as T_el).innerHTML : '';
        } else if (opts.contType === 'node') {
            result = getEl(opts.content, opts.parent);
        } else if (opts.contType === 'list') {
            result = getListArr(opts.content);
        } else if (opts.contType === 'form') {
            let tmp = getEl(opts.content, opts.parent),
                elem = tmp?.nodeName === 'TEMPLATE' ? tmp.content.cloneNode(true) : tmp;
            result = elem?.querySelector('form') || '';
        }
        else if (opts.contType === 'iframe') {
            result = getIframe(opts.content);
        } else if (opts.contType === 'iframes') {
            result = getMedias('iframe');
        } else if (opts.contType === 'image') {
            result = getImage(opts.content);
        } else if (opts.contType === 'images') {
            result = getMedias('image');
        } else if (opts.contType === 'video') {
            result = getVideo(opts.content);
        } else if (opts.contType === 'videos') {
            result = getMedias('video');
        } else if (opts.contType === 'audio') {
            result = getAudio(opts.content);
        } else if (opts.contType === 'audios') {
            result = getMedias('audio');
        }
        else if (opts.contType === 'async') {
            await getAsync(opts.content).then((resp: any) => {
                result = resp;
            });
        } else if (opts.contType === 'asyncs') {
            await getAsyncs().then((resp) => {
                result = resp;
            });
        }
        else if (['input', 'file', 'textarea', 'range', 'number'].includes(opts.contType as string)) {
            let dft = { value: opts.content, ...(opts.contData ? opts.contData as T_obj : {}) }
            result = createEl(`ax-${opts.contType}`, dft);
        }
        else {
            result = opts.content;
        }
    } else if (dataType === 'Promise') {
        await opts.content.then((resp: any) => {
            result = resp;
        });
    } else if (dataType === 'AsyncFunction') {
        await opts.content.call(this).then((resp: any) => {
            result = resp;
        });
    } else if (dataType === 'Function') {
        result = opts.content.call(this);
    } else if (dataType === 'Object' || dataType === 'Array') {
        result = deepClone(opts.content);
    } else if (dataType.includes('HTML') && opts.contType === 'list') {
        result = getListArr(opts.content);
    } else {
        result = opts.content;
    }
    opts.cb && opts.cb.call(this, result);
    return result;
}
export default getContent;
