import { NativeModules } from 'react-native'

import { createInteractor } from '../architecture/Interactor'
import { check } from '../utility/check'
import { log } from '../utility/log'
import { checkJSONElement, createJSONElement } from '../utility/json'

export const createDependency = () => {}

type RegisterInteractor = {
    setUserID(id: string): void
    clearUserID(): void
    setUserEmail(email: string): void
    clearUserEmail(): void
    setUserPhone(phone: string): void
    clearUserPhone(): void

    setUserAttribute(option: { key: string, value: any }): void
    removeUserAttribute(key: string): void
    clearUserAttributes(): void

    setUserAlias(key: string, value: string): void
    removeUserAlias(key: string): void
    clearUserAlias(): void

    clearUser(): void

    setDeviceAlias(key: string, value: string): void
    removeDeviceAlias(key: string): void
    clearDeviceAlias(): void

    registerPushToken(token: string): void
}

createDependency.RegisterModule = () => ({
    interactor: createInteractor<RegisterInteractor>(NativeModules.RegisterInteractor),
})

export type RegisterModule = ReturnType<typeof createRegisterModule>

export const createRegisterModule= () => {
    // create dependency
    const { interactor } = createDependency.RegisterModule()

    // define method
    const setUserID = (id: string) => {
        if (!check.string(id)) {
            log.unmatchedType('id', 'string')
            return
        }

        interactor.setUserID(id)
    }

    const clearUserID = () => {
        interactor.clearUserID()
    }

    const setUserEmail = (email: string) => {
        if (!check.string(email)) {
            log.unmatchedType('email', 'string')
            return
        }
        
        interactor.setUserEmail(email)
    }

    const clearUserEmail = () => {
        interactor.clearUserEmail()
    }

    const setUserPhone = (phone: string) => {
        if (!check.string(phone)) {
            log.unmatchedType('phone', 'string')
            return
        }

        interactor.setUserPhone(phone)
    }

    const clearUserPhone = () => {
        interactor.clearUserPhone()
    }

    const setUserAttribute = (key: string, value: any) => {
        if (!check.string(key)) {
            log.unmatchedType('key', 'string')
            return
        }

        if (check.defined(value) && !checkJSONElement(value)) {
            log.nonJSONValue('value')
            value = createJSONElement(value)
        }

        interactor.setUserAttribute({ key, value })
    }

    const removeUserAttribute = (key: string) => {
        if (!check.string(key)) {
            log.unmatchedType('key', 'string')
            return
        }

        interactor.removeUserAttribute(key)
    }

    const clearUserAttributes = () => {
        interactor.clearUserAttributes()
    }

    const setUserAlias = (key: string, value: string) => {
        if (!check.string(key)) {
            log.unmatchedType('key', 'string')
            return
        }
        if (!check.string(value)) {
            log.unmatchedType('value', 'string')
            return
        }

        interactor.setUserAlias(key, value)
    }

    const removeUserAlias = (key: string) => {
        if (!check.string(key)) {
            log.unmatchedType('key', 'string')
            return
        }

        interactor.removeUserAlias(key)
    }

    const clearUserAlias = () => {
        interactor.clearUserAlias()
    }

    const clearUser = () => {
        interactor.clearUser()
    }

    const setDeviceAlias = (key: string, value: string) => {
        if (!check.string(key)) {
            log.unmatchedType('key', 'string')
            return
        }
        if (!check.string(value)) {
            log.unmatchedType('value', 'string')
            return
        }

        interactor.setDeviceAlias(key, value)
    }


    const removeDeviceAlias = (key: string) => {
        if (!check.string(key)) {
            log.unmatchedType('key', 'string')
            return
        }

        interactor.removeDeviceAlias(key)
    }
    
    const clearDeviceAlias = () => {
        interactor.clearDeviceAlias()
    }

    const registerPushToken = (token: string) => {
        if (!check.string(token)) {
            log.unmatchedType('token', 'string')
            return
        }

        interactor.registerPushToken(token)
    }

    // create object
    return {
        setUserID,
        clearUserID,
        setUserEmail,
        clearUserEmail,
        setUserPhone,
        clearUserPhone,

        setUserAttribute,
        removeUserAttribute,
        clearUserAttributes,

        setUserAlias,
        removeUserAlias,
        clearUserAlias,

        clearUser,

        setDeviceAlias,
        removeDeviceAlias,
        clearDeviceAlias,

        registerPushToken,
    }
}
