// Path: opfpush/src/main/java/org/onepf/opfpush/model/State.java
// public enum State {
// 
//     /**
//      * Indicates that an unregistration has been completed.
//      */
//     UNREGISTERED(0),
// 
//     /**
//      * Indicates that a registration has been completed.
//      */
//     REGISTERED(2),
// 
//     /**
//      * Indicates that a registration is being performed.
//      */
//     REGISTERING(3);
// 
//     private int value;
// 
//     State(int value) {
//         this.value = value;
//     }
// 
//     public int getValue() {
//         return value;
//     }
// 
//     @Nullable
//     public static State fromValue(final int fromValue) {
//         final State[] values = values();
//         for (final State state : values) {
//             final int stateValue = state.getValue();
//             if (stateValue == fromValue) {
//                 return state;
//             }
//         }
// 
//         return null;
//     }
// }
// 
// Path: opfpush/src/main/java/org/onepf/opfpush/pushprovider/PushProvider.java
// public interface PushProvider {
//     /**
//      * Initiates the registration of the provider. Must be async.
//      * <p/>
//      * Intended for the internal use, should never be called directly.
//      * To start the registration call {@link org.onepf.opfpush.OPFPushHelper#register()}.
//      */
//     void register();
// 
//     /**
//      * Initiates the unregistering of the provider. Must be async.
//      * <p/>
//      * Intended for internal use, should never be called directly.
//      * To start registration call {@link org.onepf.opfpush.OPFPushHelper#unregister()}.
//      */
//     void unregister();
// 
//     /**
//      * Checks whether the provider is available.
//      *
//      * @return The instance of {@link org.onepf.opfpush.model.AvailabilityResult}
//      * that contains result of availability check.
//      */
//     @NonNull
//     AvailabilityResult getAvailabilityResult();
// 
//     /**
//      * Checks whether the application was successfully registered on the service.
//      *
//      * @return {@code true} if the application was successfully registered on the service, otherwise false.
//      */
//     boolean isRegistered();
// 
//     /**
//      * Returns the registration ID or null if provider isn't registered.
//      *
//      * @return The registration ID or null if provider isn't registered.
//      */
//     @Nullable
//     String getRegistrationId();
// 
//     /**
//      * Returns the name of the provider. Must be unique for all providers.
//      *
//      * @return The name of the provider.
//      */
//     @NonNull
//     String getName();
// 
//     /**
//      * Returns the package of the application that contains API of the provider.
//      * Usually, this is a store application.
//      *
//      * @return The package of the application that contains API of the provider.
//      */
//     @Nullable
//     String getHostAppPackage();
// 
//     /**
//      * Returns the {@link NotificationMaker} object associated with provider.
//      *
//      * @return The {@link NotificationMaker} instance.
//      */
//     @NonNull
//     NotificationMaker getNotificationMaker();
// 
//     /**
//      * Verify that application manifest contains all needed permissions.
//      *
//      * @param checkManifestHandler If not null an exception isn't thrown.
//      * @throws java.lang.IllegalStateException If not all required permissions and components have been
//      *                                         described in the AndroidManifest.xml file.
//      */
//     void checkManifest(@Nullable CheckManifestHandler checkManifestHandler);
// 
//     /**
//      * Callback method, that called when the application state change, like update to new version,
//      * or system state changed, like update firmware to a newer version.
//      * <p/>
//      * If this method is called, your registration becomes invalid
//      * and you have to reset all saved registration data.
//      */
//     void onRegistrationInvalid();
// 
//     /**
//      * Callback method for notify that the provider became unavailable.
//      * In this method you have to reset all saved registration data.
//      */
//     void onUnavailable();
// }


import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.onepf.opfpush.model.State;
import org.onepf.opfpush.pushprovider.PushProvider;
import org.onepf.opfutils.OPFChecks;
import org.onepf.opfutils.OPFLog;
import org.onepf.opfutils.OPFPreferences;
import java.util.Locale;
import static org.onepf.opfpush.model.State.UNREGISTERED;
/*
 * Copyright 2012-2015 One Platform Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onepf.opfpush;





/**
 * @author Kirill Rozov
 * @author Roman Savin
 * @since 01.10.14.
 */
@SuppressWarnings("PMD.AvoidSynchronizedAtMethodLevel")
final class Settings {

    private static final String KEY_LAST_PROVIDER_NAME = "last_provider_name";
    private static final String KEY_STATE = "state";
    private static final String KEY_LAST_ANDROID_ID = "android_id";
    private static final String KEY_UNREGISTERING_PROVIDER_PREFIX = "unregistering_provider_";
    private static final String KEY_REGISTERING_PROVIDER_PREFIX = "registering_provider_";
    private static final String KEY_PENDING_REGISTRATION_PROVIDER = "pending_registration_provider";
    private static final String KEY_PENDING_UNREGISTRATION_PROVIDER = "pending_unregistration_provider";

    private static final String OPF_CORE_POSTFIX = "opfpush";

    private static volatile Settings instance;

    @NonNull
    private final OPFPreferences preferences;

    private Settings(@NonNull final Context context) {
        preferences = new OPFPreferences(context, OPF_CORE_POSTFIX);
    }

    @SuppressWarnings("PMD.NonThreadSafeSingleton")
    public static Settings getInstance(@NonNull final Context context) {
        OPFChecks.checkThread(true);
        if (instance == null) {
            instance = new Settings(context);
        }

        return instance;
    }

    @NonNull
// Path: opfpush/src/main/java/org/onepf/opfpush/model/State.java
// public enum State {
// 
//     /**
//      * Indicates that an unregistration has been completed.
//      */
//     UNREGISTERED(0),
// 
//     /**
//      * Indicates that a registration has been completed.
//      */
//     REGISTERED(2),
// 
//     /**
//      * Indicates that a registration is being performed.
//      */
//     REGISTERING(3);
// 
//     private int value;
// 
//     State(int value) {
//         this.value = value;
//     }
// 
//     public int getValue() {
//         return value;
//     }
// 
//     @Nullable
//     public static State fromValue(final int fromValue) {
//         final State[] values = values();
//         for (final State state : values) {
//             final int stateValue = state.getValue();
//             if (stateValue == fromValue) {
//                 return state;
//             }
//         }
// 
//         return null;
//     }
// }
// 
// Path: opfpush/src/main/java/org/onepf/opfpush/pushprovider/PushProvider.java
// public interface PushProvider {
//     /**
//      * Initiates the registration of the provider. Must be async.
//      * <p/>
//      * Intended for the internal use, should never be called directly.
//      * To start the registration call {@link org.onepf.opfpush.OPFPushHelper#register()}.
//      */
//     void register();
// 
//     /**
//      * Initiates the unregistering of the provider. Must be async.
//      * <p/>
//      * Intended for internal use, should never be called directly.
//      * To start registration call {@link org.onepf.opfpush.OPFPushHelper#unregister()}.
//      */
//     void unregister();
// 
//     /**
//      * Checks whether the provider is available.
//      *
//      * @return The instance of {@link org.onepf.opfpush.model.AvailabilityResult}
//      * that contains result of availability check.
//      */
//     @NonNull
//     AvailabilityResult getAvailabilityResult();
// 
//     /**
//      * Checks whether the application was successfully registered on the service.
//      *
//      * @return {@code true} if the application was successfully registered on the service, otherwise false.
//      */
//     boolean isRegistered();
// 
//     /**
//      * Returns the registration ID or null if provider isn't registered.
//      *
//      * @return The registration ID or null if provider isn't registered.
//      */
//     @Nullable
//     String getRegistrationId();
// 
//     /**
//      * Returns the name of the provider. Must be unique for all providers.
//      *
//      * @return The name of the provider.
//      */
//     @NonNull
//     String getName();
// 
//     /**
//      * Returns the package of the application that contains API of the provider.
//      * Usually, this is a store application.
//      *
//      * @return The package of the application that contains API of the provider.
//      */
//     @Nullable
//     String getHostAppPackage();
// 
//     /**
//      * Returns the {@link NotificationMaker} object associated with provider.
//      *
//      * @return The {@link NotificationMaker} instance.
//      */
//     @NonNull
//     NotificationMaker getNotificationMaker();
// 
//     /**
//      * Verify that application manifest contains all needed permissions.
//      *
//      * @param checkManifestHandler If not null an exception isn't thrown.
//      * @throws java.lang.IllegalStateException If not all required permissions and components have been
//      *                                         described in the AndroidManifest.xml file.
//      */
//     void checkManifest(@Nullable CheckManifestHandler checkManifestHandler);
// 
//     /**
//      * Callback method, that called when the application state change, like update to new version,
//      * or system state changed, like update firmware to a newer version.
//      * <p/>
//      * If this method is called, your registration becomes invalid
//      * and you have to reset all saved registration data.
//      */
//     void onRegistrationInvalid();
// 
//     /**
//      * Callback method for notify that the provider became unavailable.
//      * In this method you have to reset all saved registration data.
//      */
//     void onUnavailable();
// }


// Path: opfpush/src/main/java/org/onepf/opfpush/Settings.java
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.onepf.opfpush.model.State;
import org.onepf.opfpush.pushprovider.PushProvider;
import org.onepf.opfutils.OPFChecks;
import org.onepf.opfutils.OPFLog;
import org.onepf.opfutils.OPFPreferences;
import java.util.Locale;
import static org.onepf.opfpush.model.State.UNREGISTERED;

/*
 * Copyright 2012-2015 One Platform Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onepf.opfpush;





/**
 * @author Kirill Rozov
 * @author Roman Savin
 * @since 01.10.14.
 */
@SuppressWarnings("PMD.AvoidSynchronizedAtMethodLevel")
final class Settings {

    private static final String KEY_LAST_PROVIDER_NAME = "last_provider_name";
    private static final String KEY_STATE = "state";
    private static final String KEY_LAST_ANDROID_ID = "android_id";
    private static final String KEY_UNREGISTERING_PROVIDER_PREFIX = "unregistering_provider_";
    private static final String KEY_REGISTERING_PROVIDER_PREFIX = "registering_provider_";
    private static final String KEY_PENDING_REGISTRATION_PROVIDER = "pending_registration_provider";
    private static final String KEY_PENDING_UNREGISTRATION_PROVIDER = "pending_unregistration_provider";

    private static final String OPF_CORE_POSTFIX = "opfpush";

    private static volatile Settings instance;

    @NonNull
    private final OPFPreferences preferences;

    private Settings(@NonNull final Context context) {
        preferences = new OPFPreferences(context, OPF_CORE_POSTFIX);
    }

    @SuppressWarnings("PMD.NonThreadSafeSingleton")
    public static Settings getInstance(@NonNull final Context context) {
        OPFChecks.checkThread(true);
        if (instance == null) {
            instance = new Settings(context);
        }

        return instance;
    }

    @NonNull
    public synchronized State getState() {