import { Column, Entity, getRepository, JoinColumn, ManyToOne, OneToMany, OneToOne, PrimaryGeneratedColumn, UpdateResult } from 'typeorm';
import { PhoneContactEntity } from './phone-contact.entity';
import { CompanyEntity } from './company.entity';
import { CharacterEntity } from './character.entity';
import { GpsEntryEntity } from './gps.entity';
import { ItemEntity } from './item.entity';
import { PhoneAvatarEntity } from './phone-avatar.entity';

export type PhoneApp = 'call' | 'messages';

export type PhoneSettings = {
    wallpaperLockScreen: string;
    wallpaper: string;
    timeFormat: number;
    btpairs: {
        id: number;
        name: string;
    }[];
    silent: boolean;
    airplane: boolean;
    pin?: string;
    mugid?: number;
    ringtone: string;
};

export type AppDataCallHistoryEntry = {
    number: string;
    type: 'out' | 'fail' | 'in';
    time: number;
};

export type PhoneStorage = {
    settings: PhoneSettings;
    app: {
        call: {
            history: AppDataCallHistoryEntry[];
        };
    };
};

@Entity('phones')
export class PhoneEntity {
    @PrimaryGeneratedColumn() id: number;
    @Column({ unique: true, length: 16 }) number: string;
    @Column({ type: 'int', nullable: true }) account_id: number;
    @Column({ type: 'int', nullable: true }) character_id: number;
    @Column({ type: 'varchar', length: 24, nullable: true }) character_name: string;
    @Column({ type: 'int', nullable: true }) company_id: number;
    @Column({ type: 'int', nullable: true }) faction_id: number;
    @Column({ type: 'json', default: '{}' }) storage: PhoneStorage;
    @Column({ type: 'int', nullable: true, default: null }) item_id: number | null;
    @Column({ type: 'varchar', length: 8, nullable: true }) color: string | null;
    @Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) created: string;
    @Column({ type: 'tinyint' }) on: boolean;
    @Column({ type: 'tinyint' }) main: boolean;

    @OneToMany(() => PhoneContactEntity, (contact) => contact.phone)
    contacts: PhoneContactEntity[];

    @ManyToOne(() => CompanyEntity, (company) => company.phones)
    @JoinColumn({
        name: 'company_id',
        referencedColumnName: 'id',
    })
    company: CompanyEntity;

    @ManyToOne(() => CharacterEntity, (character) => character.phones)
    @JoinColumn({
        name: 'character_id',
        referencedColumnName: 'id',
    })
    character: CharacterEntity;

    @OneToMany(() => GpsEntryEntity, (gpsEntry) => gpsEntry.phone)
    @JoinColumn({
        referencedColumnName: 'phone_id',
    })
    gpsEntries: GpsEntryEntity[];

    @OneToOne(() => ItemEntity)
    @JoinColumn({
        name: 'item_id',
        referencedColumnName: 'id',
    })
    item?: ItemEntity;

    @OneToOne(() => PhoneAvatarEntity)
    @JoinColumn({
        name: 'id',
        referencedColumnName: 'phone_id',
    })
    avatar?: PhoneAvatarEntity;

    async saveStorage(): Promise<UpdateResult> {
        return await getRepository(PhoneEntity).update(this.id, {
            storage: this.storage,
        });
    }

    async saveAvatar(key: string): Promise<UpdateResult> {
        return await getRepository(PhoneAvatarEntity)
            .createQueryBuilder()
            .insert()
            .values({
                phone_id: this.id,
                number: this.number,
                file: key,
            })
            .orUpdate(['file'])
            .execute();
    }

    beingTracedBy: PlayerMp[] = [];
    usedBy: number;
    locked: boolean = true;

    getOwnerName(): string | null {
        return this.character_id !== null ? this.character_name.replace(/_/g, ' ') : this.character_name;
    }
}
