package com.phlx.anchorcollect.data;

import android.annotation.SuppressLint;
import android.app.Application;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;

import com.phlx.anchorcollect.ui.bind.BindVM;
import com.phlx.anchorcollect.ui.feedback.FeedbackVM;
import com.phlx.anchorcollect.ui.fragment.vm.BasicsCollectVM;
import com.phlx.anchorcollect.ui.fragment.vm.BreedingRecordVM;
import com.phlx.anchorcollect.ui.fragment.vm.ImmunRecordVM;
import com.phlx.anchorcollect.ui.fragment.vm.MedicalRecordVM;
import com.phlx.anchorcollect.ui.fragment.vm.PerformanceVM;
import com.phlx.anchorcollect.ui.fragment.vm.WeightManVM;
import com.phlx.anchorcollect.ui.home.HomeVM;
import com.phlx.anchorcollect.ui.info.CattleVM;
import com.phlx.anchorcollect.ui.labelchange.LabelChangeVM;
import com.phlx.anchorcollect.ui.labelchange.list.ExchangeListVM;
import com.phlx.anchorcollect.ui.login.LoginVM;
import com.phlx.anchorcollect.ui.main.MainVM;
import com.phlx.anchorcollect.ui.setting.SettingVM;
import com.phlx.anchorcollect.ui.setting.SyncVM;
import com.phlx.anchorcollect.ui.splash.SplashVM;


/**
 *
 */
public class VMFactory extends ViewModelProvider.NewInstanceFactory {
    @SuppressLint("StaticFieldLeak")
    private static volatile VMFactory INSTANCE;
    private final Application mApplication;
    private Repository repository;

    public static VMFactory getInstance(Application application) {
        if (INSTANCE == null) {
            synchronized (VMFactory.class) {
                if (INSTANCE == null) {
                    INSTANCE = new VMFactory(application, Injection.provideRepository());
                }
            }

        }
        return INSTANCE;
    }

    public void refreshRepository() {
        if (repository != null) {
            repository = null;
            Injection.destroyRepository();
            repository = Injection.provideRepository();
        }
    }

    @VisibleForTesting
    public static void destroyInstance() {
        INSTANCE = null;
    }

    private VMFactory(Application application, Repository repository) {
        this.mApplication = application;
        this.repository = repository;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        if (modelClass.isAssignableFrom(SplashVM.class)) {
            return (T) new SplashVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(LoginVM.class)) {
            return (T) new LoginVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(HomeVM.class)) {
            return (T) new HomeVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(MainVM.class)) {
            return (T) new MainVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(BasicsCollectVM.class)) {
            return (T) new BasicsCollectVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(PerformanceVM.class)) {
            return (T) new PerformanceVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(MedicalRecordVM.class)) {
            return (T) new MedicalRecordVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(ImmunRecordVM.class)) {
            return (T) new ImmunRecordVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(BreedingRecordVM.class)) {
            return (T) new BreedingRecordVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(WeightManVM.class)) {
            return (T) new WeightManVM(mApplication, repository);



        } else if (modelClass.isAssignableFrom(CattleVM.class)) {
            return (T) new CattleVM(mApplication, repository);
        } else if (modelClass.isAssignableFrom(SettingVM.class)) {
            return (T) new SettingVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(BindVM.class)) {
            return (T) new BindVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(LabelChangeVM.class)) {
            return (T) new LabelChangeVM(mApplication, repository);
        } else if (modelClass.isAssignableFrom(ExchangeListVM.class)) {
            return (T) new ExchangeListVM(mApplication, repository);
        } else if (modelClass.isAssignableFrom(FeedbackVM.class)) {
            return (T) new FeedbackVM(mApplication, repository);

        } else if (modelClass.isAssignableFrom(SyncVM.class)) {
            return (T) new SyncVM(mApplication, repository);
        }
        throw new IllegalArgumentException("Unknown ViewModel class: " + modelClass.getName());
    }
}
