//Form
function Form(el, data, okCallback, cancelCallback){
    let backUp = {};
    let formBody = document.createElement('div');
    let okButton = document.createElement('button');
    okButton.innerHTML = 'OK';

    let cancelButton = document.createElement('button');
    cancelButton.innerHTML = 'Cancel';

    formBody.innerHTML = '<h1>тут будет форма после перервы</h1>';
    const table = document.createElement('table');
    formBody.append(table);

    let flag = false;
    this.validators     = {};

    //Отображение
    for (const key in data) {
        let tr = document.createElement('tr');
        let th = document.createElement('th');
        let td = document.createElement('td');
        let tdError = document.createElement('td');
        let strError = '';
        //Many Inputs
        let inp = inputCreators[data[key].constructor.name](key, data[key], (value) => data[key] = value);

        //Sync
        //let inp = document.createElement('input');
        //inp.value = data[key];
        //inp.oninput = () => data[key] = inp.value;

        //Mandatory
        if(data[key] === '') {
            inp.style.border = '2px solid #f00';
            td.append(inp);
            flag = false;
        } else {
            td.append(inp);
            flag = true;
        }
        if (key.slice(0,1) === "*") {
            th.innerHTML = `<strong>${key.slice(1)} <sup style="color: red">*</sup></strong>`;
        } else {
            th.textContent = key;
        }

        tr.append(th);
        tr.append(td);
        table.append(tr);

        //Validators / Validators messages
        inp.onchange = () => {
            if(data[key] === '') {
                inp.style.border = '2px solid #f00';
                flag = false;
            }
            else {
                inp.style.border = '2px solid #000';
                flag = true;
            }
            if (key in this.validators) {
                if (strError !== '') strError = '';
                let res = this.validators[key](data[key], key, data, inp);
                if (res === true){
                    strError = res.toString();
                    tdError.style.color = '#000';
                    flag = true;
                }
                else {
                    strError = res.toString();
                    tdError.style.color = '#F00';
                    flag = false;
                }
                tdError.textContent = strError;
                tr.append(tdError);
            }
        }
    }
    if (typeof okCallback === 'function'){
        formBody.appendChild(okButton);
        if (flag === true){
            okButton.disabled = false;
            okCallback(data);
            okButton.onclick = (e) => {
                console.log(this);
                this.okCallback(e);
            }
        }
        else {
            okButton.disabled = true;
        }
    }
    if (typeof cancelCallback === 'function'){
        formBody.appendChild(cancelButton);
        cancelButton.onclick = () => {
            backUp = {...data};
            table.remove();
            cancelCallback();
        }
    }

    el.appendChild(formBody);
    this.okCallback     = okCallback;
    this.cancelCallback = cancelCallback;
    this.data           = data;
}

//Many Inputs
let inputCreators = {
    String(key, value, oninput){
        let input = document.createElement('input')
        //Password
        if (value.includes('*')){
            input.type = 'password'
            input.value = ''
            input.placeholder = 'password'
        } else {
            input.type = 'text'
            input.value = value
            input.placeholder = key
        }
        input.oninput     = () => oninput(input.value)
        return input
    },
    Boolean(key, value, oninput){
        let input = document.createElement('input');
        input.type = 'checkbox';
        input.checked = value;
        input.oninput     = () => oninput(input.checked);
        return input;
    },
    Date(key, value, oninput){
        let offset = value.getTimezoneOffset();
        let now = value.getTime();
        let nowPlusOffset = new Date(now - offset * 60 * 1000);

        let input = document.createElement('input');
        input.type = 'datetime-local';
        input.value       = nowPlusOffset.toISOString().slice(0, -1);
        input.oninput     = () => oninput(new Date(input.value));
        return input;
    }
}

let form = new Form(formContainer, {
    '*name': 'Anakin',
    surname: 'Skywalker',
    married: true,
    birthday: new Date((new Date).getTime() - 86400000 * 30 * 365)
}, () => console.log('ok'),() => console.log('cancel') )
form.okCallback = () => console.log('ok2');

form.validators.surname = (value, key, data, input) =>
    value.length > 2 && value[0].toUpperCase() === value[0] && !value.includes(' ')
        ? true : 'Wrong name'
console.log(form)