import React from 'react';

class Auth {
    constructor() {
        this.token = '';
        /**
         *
         * @type {boolean}
         */
        this.is = false;
        this.evt = {};
        this.change = this.change.bind(this);
        this.onChange = this.onChange.bind(this);
        this.logout = this.logout.bind(this);
        if(process.browser) {
            let tmp_token = window.localStorage.getItem('jwt');
            if(null !== tmp_token && '' !== tmp_token.trim()) {
                this.token = tmp_token;
                this.is = true;
                this.change();
            }
        }
    }

    addToken(token) {
        this.is = true;
        this.token = token;
        if(process.browser) {
            window.localStorage.setItem('jwt', this.token);
        }
        this.change();
    }

    /**
     * Client Side Invalidation
     * @todo connect with server side
     */
    logout() {
        if(process.browser) {
            window.localStorage.removeItem('jwt');
        }
        this.token = '';
        this.is = false;
        this.change();
    }

    change() {
        for(let name in this.evt) {
            if(this.evt.hasOwnProperty(name)) {
                this.evt[name]();
            }
        }
    }

    onChange(cb) {
        let rnd = Math.random().toString(36).substring(7);
        if(this.evt.hasOwnProperty(rnd)) {
            // when id already exists, start again to create new
            return this.onChange(cb);
        }

        this.evt[rnd] = cb;
        return rnd;
    }

    offChange(id) {
        if(this.evt.hasOwnProperty(id)) {
            delete this.evt[id];
        }
    }
}

// single instance / singleton
const singleI = {
    a: new Auth()
};

const auth = singleI.a;
export {auth};

/**
 * provider function to wrap a react component, will inject
 * @param WrappedComponent
 *
 * @todo implement loggedIn prop, currently is empty all the time and events and everything doesnt work here as expected
 */
export default function provideAuth(WrappedComponent) {
    return class extends React.Component {
        state = {
            token: '',
            is: false
        };

        componentDidMount(){
            this.setState({
                token: singleI.a.token,
                is: singleI.a.is
            });

            this.evt_id = singleI.a.onChange(() => {
                this.setState({
                    token: singleI.a.token,
                    is: singleI.a.is
                });
            })
        }

        componentWillUnmount() {
            singleI.a.offChange(this.evt_id);
        }

        render() {
            return <WrappedComponent auth={singleI.a} {...this.props} loggedIn={this.state.is}/>;
        }
    };
}

export var logout = singleI.a.logout;