async function initApp() {
    const inputCustomerEmail = document.getElementById('customer-email');
    const inputUsername = document.getElementById('username');
    const inputLoginPassword = document.getElementById('login-password');
    const inputLoginRoleEmployee = document.getElementById('employee-login');
    const inputLoginRoleCustomer = document.getElementById('customer-login');
    const inputEmployeePassword = document.getElementById('employee-password');
    const inputCustomerFirstname = document.getElementById(
        'customer-firstname'
    );
    const inputCustomerLastname = document.getElementById('customer-lastname');
    const inputEmployeeEmail = document.getElementById('employee-email');
    const inputEmployeeFirstname = document.getElementById(
        'employee-firstname'
    );
    const inputEmployeeLastname = document.getElementById('employee-lastname');
    const inputStreet = document.getElementById('street');
    const inputZip = document.getElementById('zip');
    const inputCity = document.getElementById('city');
    const inputCountry = document.getElementById('country');
    const inputCompany = document.getElementById('company');

    const formRegisterCustomer = document.getElementById(
        'form-register-customer'
    );
    const formRegisterEmployee = document.getElementById(
        'form-register-employee'
    );
    const formLogin = document.getElementById('form-login');
    const formRefresh = document.getElementById('form-refresh');
    const formLogout = document.getElementById('form-logout');
    const formAuthenticate = document.getElementById('form-authenticate');

    const refreshTokenField = document.getElementById('refreshToken');
    const accessTokenField = document.getElementById('accessToken');
    const authenticateArea = document.getElementById('authenticatedArea');

    const backend = 'http://localhost:2222';

    let accessToken;
    let refreshToken;

    function generateRandomUser() {
        const randomNumber = Math.floor(Math.random() * 1000000);
        return {
            mail: `user${randomNumber}@example.com`,
            firstname: `first${randomNumber}`,
            lastname: `last${randomNumber}`,
            street: `street${randomNumber}`,
            city: `city${randomNumber}`,
            zip: randomNumber,
            country: `country${randomNumber}`,
            company: `company${randomNumber}`,
        };
    }

    function checkStatus(response) {
        if (response.status >= 200 && response.status < 300) {
            return response;
        }
        const error = new Error(response.statusText);
        error.response = response;
        throw error;
    }

    async function getJson(endpoint, token) {
        return fetch(`${backend}${endpoint}`, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                Accept: 'application/json',
                authorization: `Bearer ${token}`,
            },
            mode: 'cors',
            credentials: 'include', // permit server to store cookies in response in the browser "local storage"
        }).then(checkStatus);
    }

    async function postJson(endpoint, params, token) {
        return fetch(`${backend}${endpoint}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                Accept: 'application/json',
                authorization: `Bearer ${token}`,
            },
            mode: 'cors',
            credentials: 'include', // permit server to store cookies in response in the browser "local storage"
            body: JSON.stringify(params),
        }).then(checkStatus);
    }

    function resetInputForm() {
        const randomUser = generateRandomUser();
        inputCustomerEmail.value = randomUser.mail;
        inputCustomerFirstname.value = randomUser.firstname;
        inputCustomerLastname.value = randomUser.lastname;
        inputEmployeeEmail.value = randomUser.mail;
        inputEmployeeFirstname.value = randomUser.firstname;
        inputEmployeeLastname.value = randomUser.lastname;
        inputEmployeePassword.value = 'password';
        inputStreet.value = randomUser.street;
        inputCity.value = randomUser.city;
        inputZip.value = randomUser.zip;
        inputCountry.value = randomUser.country;
        inputCompany.value = randomUser.company;
    }

    function registerCustomerEventHandler(event) {
        event.preventDefault();

        const mail = event.target.email.value;
        const firstname = event.target.firstname.value;
        const lastname = event.target.lastname.value;
        const street = event.target.street.value;
        const city = event.target.city.value;
        const zip = event.target.zip.valueAsNumber;
        const country = event.target.country.value;
        const company = event.target.company.value;

        postJson(
            '/customers',
            {
                mail,
                firstname,
                lastname,
                street,
                city,
                zip,
                country,
                company,
            },
            accessToken
        )
            .then((response) => response.json())
            .then((response) => {
                if (response.initialPassword) {
                    inputLoginPassword.value = response.initialPassword;
                }

                inputUsername.value = inputCustomerEmail.value;
                inputLoginRoleCustomer.checked = true;

                resetInputForm();
            });
    }

    function registerEmployeeEventHandler(event) {
        event.preventDefault();

        const mail = event.target.email.value;
        const password = event.target.password.value;
        const firstname = event.target.firstname.value;
        const lastname = event.target.lastname.value;

        postJson(
            '/employees',
            { mail, password, firstname, lastname },
            accessToken
        ).then(() => {
            inputUsername.value = inputEmployeeEmail.value;
            inputLoginPassword.value = inputEmployeePassword.value;
            inputLoginRoleEmployee.checked = true;
            resetInputForm();
        });
    }

    function loginEventHandler(event) {
        event.preventDefault();

        const username = event.target.username.value;
        const password = event.target.password.value;
        const role = event.target.role.value;

        postJson('/auth/login', { username, password, role })
            .then((response) => response.json())
            .then((response) => {
                if (response.success) {
                    accessToken = response.accessToken;
                    refreshToken = response.refreshToken;
                    accessTokenField.textContent = accessToken;
                    refreshTokenField.textContent = refreshToken;
                }
            });
    }

    function refreshEventHandler(event) {
        event.preventDefault();

        postJson('/auth/refresh_token', {}, refreshToken)
            .then((response) => response.json())
            .then((response) => {
                if (response.success) {
                    accessToken = response.accessToken;
                    accessTokenField.textContent = accessToken;
                }
            });
    }

    function logoutEventHandler(event) {
        event.preventDefault();

        postJson('/auth/logout', accessToken)
            .then((response) => response.json())
            .then((response) => {
                if (response.success) {
                    accessTokenField.textContent = '';
                    refreshTokenField.textContent = '';
                    authenticateArea.textContent = '';
                }
            });
    }

    function authenticateEventHandler(event) {
        event.preventDefault();

        getJson('/customers', accessToken)
            .then((response) => response.json())
            .then((response) => {
                if (response.success) {
                    console.dir(response.customers);
                    authenticateArea.textContent = JSON.stringify(
                        response.customers
                    );
                }
            });
    }

    resetInputForm();

    formLogin.addEventListener('submit', loginEventHandler);
    formRegisterCustomer.addEventListener(
        'submit',
        registerCustomerEventHandler
    );
    formRegisterEmployee.addEventListener(
        'submit',
        registerEmployeeEventHandler
    );
    formRefresh.addEventListener('submit', refreshEventHandler);
    formLogout.addEventListener('submit', logoutEventHandler);
    formAuthenticate.addEventListener('submit', authenticateEventHandler);
}
// register initApp
document.addEventListener('DOMContentLoaded', initApp);
