import {
    isString,
    isNumber,
    isValidUrl,
    isValidISOCode,
} from './Common/Validate';

const gender = ['Male', 'Female', 'Unknown'] as const;
export type GenderType = (typeof gender)[number];

const provider = ['', 'network', 'full', 'gps', 'passive'] as const;
export type ProviderType = (typeof provider)[number];

export type LocationType = {
    latitude: number;
    longitude: number;
    provider: ProviderType;
};

export class BluestackPreference {
    private age!: number;
    private location!: LocationType;
    private consentFlag!: number;
    private language!: string;
    private gender!: string;
    private keyword!: string;
    private contentUrl!: string;

    public setAge(age: number): void {
        if (!isNumber(age)) {
            throw new Error('`age` expects a number value');
        } else {
            this.age = age;
        }
    }

    public isProviderType = (x: any): x is ProviderType => provider.includes(x);

    public setLocation(location: LocationType, consentFlag: number): void {
        if (!this.isProviderType(location.provider)) {
            throw new Error('`provider` expects a number value');
        } else if (!isNumber(location.latitude)) {
            throw new Error('`latitude` expects a number value');
        } else if (!isNumber(location.longitude)) {
            throw new Error('`longitude` expects a number value');
        } else {
            this.location = location;
        }

        if (!isNumber(consentFlag)) {
            throw new Error('`consentFlag` expects a number value');
        } else {
            this.consentFlag = consentFlag;
        }
    }

    public setLanguage(language: string): void {
        if (!isValidISOCode(language)) {
            throw new Error(
                '`language` expects a (ISO Code) string value. Example: `en`'
            );
        } else {
            this.language = language;
        }
    }

    public isGenderType = (x: any): x is GenderType => gender.includes(x);

    public setGender(g: GenderType): void {
        if (this.isGenderType(g)) {
            this.gender = g;
        } else {
            throw new Error(
                '`gender` expects a (Male, Female, Unknown) GenderType value'
            );
        }
    }

    public setKeyword(keyword: string): void {
        if (!isString(keyword)) {
            throw new Error('`keyword` expects a string value');
        } else {
            this.keyword = keyword;
        }
    }

    public setContentUrl(contentUrl: string): void {
        if (!isString(contentUrl)) {
            throw new Error('`contentUrl` expects a string value');
        } else if (!isValidUrl(contentUrl)) {
            throw new Error('`contentUrl` expects a valid HTTP or HTTPS url.');
        } else if (contentUrl.length > 512) {
            throw new Error(
                'Maximum length of a `contentUrl` is 512 characters.'
            );
        } else {
            this.contentUrl = contentUrl;
        }
    }

    public getPreferenceJSON(): string {
        const preferenceJSON = JSON.stringify(this);
        // console.log('BluestackPreference.getMNGPreference(): ' + preferenceJSON);
        return preferenceJSON;
    }
}
