package com.lody.virtual.server.accounts;

import android.accounts.Account;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Lody
 */

public class VSyncRecord {

    public int userId;
    public SyncRecordKey key;
    public int syncable = -1;
    public boolean isPeriodic = false;
    public Map<SyncExtras, PeriodicSyncConfig> configs = new HashMap<>();
    public List<SyncExtras> extras = new ArrayList<>();

    public VSyncRecord(int userId, Account account, String authority) {
        this.userId = userId;
        key = new SyncRecordKey(account, authority);
    }

    public static class SyncExtras implements Parcelable {
        Bundle extras;

        public SyncExtras(Bundle extras) {
            this.extras = extras;
        }

        SyncExtras(Parcel in) {
            this.extras = in.readBundle(getClass().getClassLoader());
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeBundle(this.extras);
        }

        public static final Parcelable.Creator<SyncExtras> CREATOR = new Parcelable.Creator<SyncExtras>() {
            @Override
            public SyncExtras createFromParcel(Parcel source) {
                return new SyncExtras(source);
            }

            @Override
            public SyncExtras[] newArray(int size) {
                return new SyncExtras[size];
            }
        };

        @Override
        public boolean equals(Object obj) {
            return VSyncRecord.equals(this.extras, ((SyncExtras) obj).extras, false);
        }
    }

    public static class SyncRecordKey implements Parcelable {

        Account account;
        String authority;

        SyncRecordKey(Account account, String authority) {
            this.account = account;
            this.authority = authority;
        }

        SyncRecordKey(Parcel in) {
            this.account = in.readParcelable(Account.class.getClassLoader());
            this.authority = in.readString();
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeParcelable(this.account, flags);
            dest.writeString(this.authority);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            SyncRecordKey that = (SyncRecordKey) o;

            if (account != null ? !account.equals(that.account) : that.account != null)
                return false;
            return authority != null ? authority.equals(that.authority) : that.authority == null;
        }

        public static final Parcelable.Creator<SyncRecordKey> CREATOR = new Parcelable.Creator<SyncRecordKey>() {
            @Override
            public SyncRecordKey createFromParcel(Parcel source) {
                return new SyncRecordKey(source);
            }

            @Override
            public SyncRecordKey[] newArray(int size) {
                return new SyncRecordKey[size];
            }
        };
    }

    public static boolean equals(Bundle a, Bundle b, boolean sameSize) {
        if (a == b) {
            return true;
        }
        if (sameSize && a.size() != b.size()) {
            return false;
        }
        if (a.size() <= b.size()) {
            Bundle smaller = a;
            a = b;
            b = smaller;
        }
        for (String key : a.keySet()) {
            if (sameSize || !isIgnoredKey(key)) {
                if (!b.containsKey(key)) {
                    return false;
                }
                //noinspection ConstantConditions
                if (!a.get(key).equals(b.get(key))) {
                    return false;
                }
            }
        }
        return true;
    }

    static class PeriodicSyncConfig implements Parcelable {

        long syncRunTimeSecs;

        public PeriodicSyncConfig(long syncRunTimeSecs) {
            this.syncRunTimeSecs = syncRunTimeSecs;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeLong(this.syncRunTimeSecs);
        }

        PeriodicSyncConfig(Parcel in) {
            this.syncRunTimeSecs = in.readLong();
        }

        public static final Parcelable.Creator<PeriodicSyncConfig> CREATOR = new Parcelable.Creator<PeriodicSyncConfig>() {
            @Override
            public PeriodicSyncConfig createFromParcel(Parcel source) {
                return new PeriodicSyncConfig(source);
            }

            @Override
            public PeriodicSyncConfig[] newArray(int size) {
                return new PeriodicSyncConfig[size];
            }
        };
    }

    private static boolean isIgnoredKey(String str) {
        return str.equals("expedited")
                || str.equals("ignore_settings")
                || str.equals("ignore_backoff")
                || str.equals("do_not_retry")
                || str.equals("force")
                || str.equals("upload")
                || str.equals("deletions_override")
                || str.equals("discard_deletions")
                || str.equals("expected_upload")
                || str.equals("expected_download")
                || str.equals("sync_priority")
                || str.equals("allow_metered")
                || str.equals("initialize");
    }
}