public class NotificationManager {
	public static final int NOTIFICATION_ADDED = 0;
	public static final int NOTIFICAITON_REMOVED = 1;
	public static final int NOTIFICATION_CHANGED = 2;
	public static final int NOTIFICATION_NO_CHANGE = 3;

	public static final String BROADCAST_NOTIFICATION_UPDATE_RESULT = "notificationUpdate";
	public static final String TAG = "NotificationManager";
	
	private static boolean isRunning=false;

	public static void manageNotificaiton(Context context) {
		if (isRunning) return;
		isRunning = true;
		
		try {
			Notificaton newNf = Server.getNotification(context);
			Notificaton oldNf = LocalData.getNotification(context);
			int result = compare(oldNf, newNf);
			updateLocalData(result,newNf,context);
			broadcastResult(result, context);   //at time of app login receiver in not registered.

		} catch (Exception e) {
			e.printStackTrace();
		}
		
		isRunning = false;
	}

	private static void updateLocalData(int result, Notificaton newNf,
			Context context) {
		LocalData.setNotification(newNf, context);
		updateNotificationAlert(result,context);		
	}

	private static void updateNotificationAlert(int result, Context context) {
		if (result == NOTIFICATION_ADDED) {
			LocalData.setNotificationAlertNotDone(context);
		} else if (result == NotificationManager.NOTIFICAITON_REMOVED) {
			LocalData.setNotificationAlertDone(context);
		} else if (result == NotificationManager.NOTIFICATION_CHANGED) {
			LocalData.setNotificationAlertNotDone(context);

		}

	}

	public static boolean isNotificationAvailable(Context context) {
		return !LocalData.getNotification(context).isEmpty();
	}

	private static void broadcastResult(int result, Context context) {
		Intent intent = new Intent(BROADCAST_NOTIFICATION_UPDATE_RESULT)
				.putExtra(BROADCAST_NOTIFICATION_UPDATE_RESULT, result);
		LocalBroadcastManager.getInstance(context).sendBroadcast(intent);

	}

	private static int compare(Notificaton oldNf, Notificaton newNf) {
		if (oldNf.isEmpty() && !newNf.isEmpty())
			return NOTIFICATION_ADDED;
		if (!oldNf.isEmpty() && newNf.isEmpty())
			return NOTIFICAITON_REMOVED;
		if (oldNf.equals(newNf))
			return NOTIFICATION_NO_CHANGE;
		if (!oldNf.isEmpty() && !newNf.isEmpty() && !oldNf.equals(newNf))
			return NOTIFICATION_CHANGED;
		return -1;
	}

} public class MainPrefs {
    public static final String PREFS_NAME = "MyPrefsFile";

    public static final String ENROLL_NO = "enroll";
    public static final String PASSWORD = "pass";
    public static final String DOB = "dob";
    public static final String BATCH = "batch";
    public static final String COLG = "colg";
    public static final String USER_NAME = "userName";        //Name of student.
    public static final String IS_FIRST_TIME = "isFirstTime";
    private static final String STARTUP_ACTIVITY_NAME = "startupActivityName";
    private static final String ONLINE_TIMETABLE_FILE_NAME = "onlineTimetableFileName";
    public static final String IS_TIMETABLE_MODIFIED = "isTimetableModified";  //True if user modifies timetable at any time in lifetime.

    public static final String SAVE_DIALOG_MSG = "dialog";
    public static final String SAVE_DIALOG_DEFAULT_MSG = "NA";


    private static SharedPreferences prefs = null;

    private static void initPrefInstance(Context context) {
        if (prefs == null) prefs = context.getSharedPreferences(PREFS_NAME, 0);
    }

    public static String getEnroll(Context context) {
        initPrefInstance(context);
        return prefs.getString(ENROLL_NO, "123");
    }

    public static String getPassword(Context context) {
        initPrefInstance(context);
        return prefs.getString(PASSWORD, "123");
    }

    public static String getDOB(Context context) {
        initPrefInstance(context);
        return prefs.getString(DOB, "123");
    }

    public static String getBatch(Context context) {
        initPrefInstance(context);
        return prefs.getString(BATCH, "123");
    }


    public static String getColg(Context context) {
        initPrefInstance(context);
        return prefs.getString(COLG, "JIIT");
    }

    public static String getUserName(Context context) {
        initPrefInstance(context);
        return prefs.getString(USER_NAME, "NA");
    }

    /**
     * get message of saved error dialog.
     *
     * @param context
     * @return
     */
    public static String getSavedDialogMsg(Context context) {
        initPrefInstance(context);
        return prefs.getString(SAVE_DIALOG_MSG, SAVE_DIALOG_DEFAULT_MSG);
    }

    public static String getStartupActivityName(Context context) {
        initPrefInstance(context);
        return prefs.getString(STARTUP_ACTIVITY_NAME, TimetableActivity.class.getSimpleName());
    }

    /**
     * FileName of timetable as stored on server.
     *
     * @param context
     * @return
     */
    public static String getOnlineTimetableFileName(Context context) {
        initPrefInstance(context);
        return prefs.getString(ONLINE_TIMETABLE_FILE_NAME, "NULL");
    }


    /**
     * Used in showing help menu at first login.
     *
     * @param context
     * @return true, if app is viewed first time after logging in.
     */
    public static boolean isFirstTime(Context context) {
        initPrefInstance(context);
        return prefs.getBoolean(IS_FIRST_TIME, true);
    }

    public static boolean isTimetableModified(Context context) {
        initPrefInstance(context);
        return prefs.getBoolean(IS_TIMETABLE_MODIFIED, false);
    }

    //UserName == StudentName
    public static void setUserName(String userName, Context context) {
        initPrefInstance(context);
        prefs.edit().putString(USER_NAME, userName).commit();
    }

    public static void setPassword(String password, Context context) {
        initPrefInstance(context);
        prefs.edit().putString(PASSWORD, password).commit();
    }

    public static void setDOB(String dob, Context context) {
        initPrefInstance(context);
        prefs.edit().putString(DOB, dob).commit();
    }

    /**
     * set meessage of dialog to be saved.
     * @param msg
     * @param context
     */
    public static void setSaveDialogMsg(String msg, Context context) {
        initPrefInstance(context);
        prefs.edit().putString(SAVE_DIALOG_MSG, msg).commit();
    }

    /**
     * set that first refresh of database is over.
     * @param context
     */
    public static void setFirstTimeOver(Context context) {
        initPrefInstance(context);
        prefs.edit().putBoolean(IS_FIRST_TIME, false).commit();
    }

    public static void storeStartupActivity(Context context, String name) {
        initPrefInstance(context);
        prefs.edit().putString(STARTUP_ACTIVITY_NAME, name).commit();
    }

    /**
     * Filename of timetable on server.
     * @param context
     * @param fileName
     */
    public static void setOnlineTimetableFileName(Context context, String fileName) {
        initPrefInstance(context);
        prefs.edit().putString(ONLINE_TIMETABLE_FILE_NAME, fileName).commit();
    }

    /**
     * set if timetable if timetable is manually modified by user or not.
     * @param context
     */
    public static void setTimetableModified(Context context) {
        initPrefInstance(context);
        prefs.edit().putBoolean(IS_TIMETABLE_MODIFIED, true).commit();
    }

    public static void close() {
        prefs = null;
    }

} public class RefreshBroadcasts {
    public static final String BROADCAST_LOGIN_RESULT = "BROADCAST_LOGIN_RESULT";
    public static final String BROADCAST_UPDATE_AVG_ATND_RESULT = "UPDATE_AVG_ATND_RESULT";
    public static final String BROADCAST_UPDATE_DETAILED_ATTENDENCE_RESULT = "UPDATE_DETAILED_ATTENDENCE_RESULT";
} public enum RefreshStatus {
    STOPPED,
    LOGGING_IN,
    REFRESHING_O,       //refresh avg attendance.
    REFRESHING_D,       //refreshing detailed attendance.
    REFRESHING_DATESHEET,
    CREATING_DB;

    public static RefreshStatus getEnumFromString(String name) {
        return RefreshStatus.valueOf(name);
    }

    public String getString() {
        return name();
    }

    /**
     * Returns messages that can be shown in UI for each phase of refresh.
     * @param context
     * @return
     */
    public static String getStatusMessage(Context context) {
        switch (RefreshDBPrefs.getStatus(context)) {

            case REFRESHING_D:
                return context.getString(R.string.refreshing_detailed_atnd);
            case REFRESHING_DATESHEET:
                return context.getString(R.string.refreshing_datesheet);
            default:
                return context.getString(R.string.refresh_in_progress);
        }
    }

} public class RefreshDbErrorDialogStore {


    static AlertDialog myDialog = null;

    /**
     * Show stored error dialog if present.
     * @param context
     */
    public static void showDialogIfPresent(Context context) {
        String dialogMsg = MainPrefs.getSavedDialogMsg(context);

        if (!dialogMsg.equals(MainPrefs.SAVE_DIALOG_DEFAULT_MSG)) {
            myDialog = createAlertDialog(dialogMsg, context);
            myDialog.show();
        }
    }

    public static void dismissIfPresent() {
        if (myDialog != null) {
            myDialog.dismiss();
            myDialog = null;
        }
    }

    private static AlertDialog createAlertDialog(String msg,
                                                final Context context) {

        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setPositiveButton(R.string.ok,
                new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int id) {
                        myDialog = null;
                        MainPrefs.setSaveDialogMsg(MainPrefs.SAVE_DIALOG_DEFAULT_MSG, context);
                    }
                });
        builder.setOnCancelListener(new DialogInterface.OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                myDialog = null;
                MainPrefs.setSaveDialogMsg(MainPrefs.SAVE_DIALOG_DEFAULT_MSG, context);
            }
        });

        builder.setMessage(msg);
        return builder.create();

    }

    /**
     * Stores message of every error dialog, So that dialog can be retrieved from UI elements.
     * @param type
     * @param result
     * @param context
     */
    public static void store(String type, int result, Context context) {

        if (type.equals(RefreshBroadcasts.BROADCAST_LOGIN_RESULT)) {
            if (result != LoginStatus.LOGIN_DONE)
                addToPrefs(LoginStatus.responseToString(context, result), context);
        } else if (type.equals(RefreshBroadcasts.BROADCAST_UPDATE_AVG_ATND_RESULT)) {
            if (result == UpdateAvgAtnd.ERROR)
                addToPrefs(context.getString(R.string.attendence_update_error),
                        context);
        } else if (type
                .equals(InitDB.BROADCAST_DATEBASE_CREATION_RESULT)) {
            if (result == CreateDatabase.ERROR)
                addToPrefs(context.getString(R.string.database_creation_error),
                        context);
            else if (result == TimetableCreateRefresh.ERROR_BATCH_UNAVAILABLE)
                addToPrefs(context.getString(R.string.invalid_batch), context);
            else if (result == TimetableCreateRefresh.ERROR_CONNECTION)
                addToPrefs(
                        context.getString(R.string.error_timetableserver_connection),
                        context);
            else if (result == TimetableCreateRefresh.ERROR_UNKNOWN)
                addToPrefs(context.getString(R.string.unknown_error), context);
        } else if (type
                .equals(RefreshBroadcasts.BROADCAST_UPDATE_DETAILED_ATTENDENCE_RESULT)) {
            if (result == UpdateDetailedAttendance.ERROR)
                addToPrefs(context.getString(R.string.attendence_update_error),
                        context);
        }

    }

    private static void addToPrefs(String msg, Context context) {
        MainPrefs.setSaveDialogMsg(msg, context);
    }

} public class ChangePasswordDialog {


    public static void show(final Activity activity) {
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        final View myView = activity.getLayoutInflater().inflate(
                R.layout.dialog_change_pass, null);

        builder.setView(myView);


        builder.setPositiveButton(android.R.string.ok,
                new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int id) {
                        String pass = ((EditText) myView
                                .findViewById(R.id.changepass_dialog_editbox))
                                .getEditableText().toString().trim();
                        if (pass.equals(""))
                            show(activity);
                        else {
                            MainPrefs.setPassword(pass, activity);
                            Toast.makeText(
                                    activity,
                                    activity.getResources()
                                            .getString(
                                                    R.string.password_changed_successfully),
                                    Toast.LENGTH_SHORT).show();
                            RefreshDBPrefs.setPasswordUptoDate(activity);

                        }
                    }

                });



        builder.setNegativeButton(R.string.cancel,
                new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });

        builder.create().show();
    }
} public class SetDOBDialog {


    public static void show(final Activity activity) {
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        final View myView = activity.getLayoutInflater().inflate(
                R.layout.dialog_set_dob, null);

        builder.setView(myView);


        builder.setPositiveButton(android.R.string.ok,
                new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int id) {
                        String dob = ((EditText) myView
                                .findViewById(R.id.set_dob_dialog_editbox))
                                .getEditableText().toString().trim();
                        Pattern pattern = Pattern.compile("\\d\\d-\\d\\d-\\d\\d\\d\\d");
                        Matcher matcher = pattern.matcher(dob);
                        if (!matcher.find()){
                            Toast.makeText(activity, activity.getString(R.string.invalid_dob_format),
                                    Toast.LENGTH_LONG).show();
                            show(activity);
                        } else {
                            MainPrefs.setDOB(dob, activity);
                            Toast.makeText(
                                    activity,
                                    activity.getResources()
                                            .getString(
                                                    R.string.dob_set_successfully),
                                    Toast.LENGTH_SHORT).show();
                        }
                    }

                });



        builder.setNegativeButton(R.string.cancel,
                new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });

        builder.create().show();
    }
} public class M {
	private static final boolean showLog = true;
	public static void log(String TAG, String text) {
		if (showLog) Log.d(TAG, text);

	/*	File logFile = new File("sdcard/log.txt");
		if (!logFile.exists()) {
			try {
				logFile.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			// BufferedWriter for performance, true to set append to file flag
			BufferedWriter buf = new BufferedWriter(new FileWriter(logFile,
					true));
			String mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
			buf.append(mydate + "     " + TAG + " --->  " + text);
			Log.d(TAG, text);
			buf.newLine();
			buf.close();
		} catch (IOException e) {
			e.printStackTrace();
		}*/
	}
} public class RefreshDBPrefs {

    public static final String REFRESH_SERVICE_STATUS = "refSStatus";


    //Name value is out of sync, would be great if someone could fix it.
    public static final String DETAILED_ATND_TIMESTAMP = "lastUpdate";
    public static final String REFRESH_START_TIMESTAMP = "refreshStartTime";
    public static final String PASSWORD_UPTO_DATE = "passUptoDate";
    public static final String WIFI_ZONE_END_RANDOMIZE_TIME = "wifiZoneEndRandomizeTime";
    private static final String AVG_ATND_TIMESTAMP = "ATND_OVERVIEW_TIMESTAMP";
    public static final String SHOW_RECENTLY_UPDATED_TAG = "showRecentlyUpdatedTag";
    private static final String IS_FIRST_REFRESH = "isFirstRefresh";
    private static final String REFRESH_END_TIMESTAMP = "refreshEndTime";

    public static final int DEFAULT_TIMESTAMP = 0;

    static SharedPreferences prefs = null;

    //Singleton init preference.
    private static void initPrefInstance(Context context) {
        if (prefs == null)
            prefs = context.getApplicationContext().getSharedPreferences(MainPrefs.PREFS_NAME, 0);
    }

    /**
     * Refresher has to use setStatus(..) before doing anything so that other part of app has info what refresher is currently doing.
     * @param status    Current status of refresh
     * @param context   Context
     */
    public static void setStatus(RefreshStatus status, Context context) {
        initPrefInstance(context);
        prefs.edit().putString(REFRESH_SERVICE_STATUS, status.getString()).commit();
    }

    /**
     * Return current status of Refresher.
     * @param context
     * @return RefreshStatus
     */
    public static RefreshStatus getStatus(Context context) {
        initPrefInstance(context);
        String str =  prefs.getString(REFRESH_SERVICE_STATUS, RefreshStatus.STOPPED.getString());
        return   RefreshStatus.getEnumFromString(str);
    }

    /**
     * Checks current status of refresh with provided status.
     */
    public static boolean isStatus(RefreshStatus status, Context context) {
        initPrefInstance(context);
        return getStatus(context) == status;
    }

    /**
     * Sets time when refresh starts.
     * @param context
     */
    public static void setRefreshStartTimestamp(Context context) {
        initPrefInstance(context);

        prefs.edit()
                .putLong(REFRESH_START_TIMESTAMP, System.currentTimeMillis())
                .commit();
    }

    private static long getRefreshStartTimeStamp(Context context) {
        initPrefInstance(context);
        return prefs.getLong(REFRESH_START_TIMESTAMP, DEFAULT_TIMESTAMP);
    }

    /**
     * Sets time when average attendance update is done.
     * @param context
     */
    public static void setAvgAttendanceRefreshTimestamp(Context context) {
        initPrefInstance(context);
        prefs.edit()
                .putLong(AVG_ATND_TIMESTAMP, System.currentTimeMillis())
                .commit();
    }

    /**
     * Gets last time when average attendance was updated.
     * @param context
     * @return
     */
    public static long getAvgAttendanceRefreshTimeStamp(Context context) {
        initPrefInstance(context);
        return prefs.getLong(AVG_ATND_TIMESTAMP, DEFAULT_TIMESTAMP);
    }

    /**
     * Sets time when detailed attendance update is done.
     * @param context
     */
    public static void setDetailedAtndRefreshTimestamp(Context context) {
        initPrefInstance(context);
        prefs.edit()
                .putLong(DETAILED_ATND_TIMESTAMP, System.currentTimeMillis())
                .commit();
    }

    /**
     * Gets last time when detailed attendance was updated.
     * @param context
     * @return
     */
    public static long getDetailedAtndRefreshTimeStamp(Context context) {
        initPrefInstance(context);
        return prefs.getLong(DETAILED_ATND_TIMESTAMP, DEFAULT_TIMESTAMP);
    }

    /**
     * Sets time when full refresh is complete.
     * @param context
     */
    public static void setRefreshEndTimestamp(Context context) {
        initPrefInstance(context);

        prefs.edit()
                .putLong(REFRESH_END_TIMESTAMP, System.currentTimeMillis())
                .commit();
    }

    /**
     * Gets end time of last refresh.
     * @param context
     * @return
     */
    public static long getRefreshEndTimeStamp(Context context) {
        initPrefInstance(context);
        return prefs.getLong(REFRESH_END_TIMESTAMP, DEFAULT_TIMESTAMP);
    }

    public static void setRecentlyUpdatedTagVisibility(boolean value, Context context) {
        initPrefInstance(context);
        prefs.edit().putBoolean(SHOW_RECENTLY_UPDATED_TAG, value).commit();
    }

    public static boolean getRecentlyUpdatedTagVisibility(Context context) {
        initPrefInstance(context);
        return prefs.getBoolean(SHOW_RECENTLY_UPDATED_TAG, false);
    }


    public static void setPasswordOutdated(Context context) {
        initPrefInstance(context);
        prefs.edit().putBoolean(PASSWORD_UPTO_DATE, false).commit();
    }

    public static void setPasswordUptoDate(Context context) {
        initPrefInstance(context);
        prefs.edit().putBoolean(PASSWORD_UPTO_DATE, true).commit();
    }


    public static boolean isPasswordUptoDate(Context context) {
        initPrefInstance(context);
        return prefs.getBoolean(PASSWORD_UPTO_DATE, true);
    }

    public static boolean canAutoRefresh(Context context) {
        return isPasswordUptoDate(context);
    }

    public static long getWifiZoneEndRandomizeTime(Context context) {
        initPrefInstance(context);
        return prefs.getLong(WIFI_ZONE_END_RANDOMIZE_TIME,
                System.currentTimeMillis());
    }

    public static void setWifiZoneEndRandomizeTime(long time, Context context) {
        initPrefInstance(context);
        prefs.edit().putLong(WIFI_ZONE_END_RANDOMIZE_TIME, time).commit();
    }


    public static boolean isFirstRefresh(Context context) {
        initPrefInstance(context);
        return prefs.getBoolean(IS_FIRST_REFRESH, true);
    }

    /**
     * Sets that first time database refresh of app is done.
     * @param context
     */
    public static void setFirstRefreshOver(Context context) {
        initPrefInstance(context);
        prefs.edit().putBoolean(IS_FIRST_REFRESH, false).commit();
    }

    /**
     * Returns if refresh is running or not.
     * @param context
     * @return
     */
    public static boolean isRunning(Context context) {
        return (getStatus(context) != RefreshStatus.STOPPED);
    }

    private static boolean isRunningFromLongTime(Context context) {
        initPrefInstance(context);
        if (isRunning(context)
                && System.currentTimeMillis() > (getRefreshStartTimeStamp(context) + 300000))
            return true;
        else
            return false;
    }

    /**
     * Resets status of refresh if it is running from more than 5 minutes.
     * @param context
     */
    public static void resetIfrunningFromLongTime(Context context) {
        initPrefInstance(context);

        if (isRunningFromLongTime(context)) {
            setStatus(RefreshStatus.STOPPED, context);
        }
    }
} public class RefreshFullDB {
    static final String TAG = "serviceLogin";
    public static final String REFRESH_TYPE = "refType";
    public static final int AUTO_REFRESH = 1;       //Refresh automatically done by app.
    public static final int MANUAL_REFRESH = 2;     //Type of refresh when user press refresh button.
    public static final int ERROR = -1;
    public static final int OK = 1;
    String enroll, pass, batch, colg, dob;
    int refreshType;        //Auto refresh or manual refresh.
    Context context;

    /**
     * @param refreshType AUTO_REFRESH 0R MANUAL_REFRESH
     * @param context
     */
    public RefreshFullDB(int refreshType, Context context) {
        this.enroll = MainPrefs.getEnroll(context);
        this.pass = MainPrefs.getPassword(context);
        this.batch = MainPrefs.getBatch(context);
        this.colg = MainPrefs.getColg(context);
        this.dob = MainPrefs.getDOB(context);
        this.refreshType = refreshType;
        this.context = context;
    }

    public int refresh() throws SubjectChangedException {
        return refresh(null);
    }


    public int refresh(CrawlerDelegate crawlerDelegate) throws SubjectChangedException {
        M.log(TAG, "refresh started");

        RefreshDBPrefs.resetIfrunningFromLongTime(context);
        if (RefreshDBPrefs.isRunning(context)) return OK;

        RefreshDBPrefs.setRefreshStartTimestamp(context);


        int result;

        try {

            if (crawlerDelegate == null) {
                RefreshDBPrefs.setStatus(RefreshStatus.LOGGING_IN, context);

                crawlerDelegate = new CrawlerDelegate(context);
                result = crawlerDelegate.login(colg, enroll, pass, dob);
                M.log(TAG, "login done result  " + result);

                broadcastResult(RefreshBroadcasts.BROADCAST_LOGIN_RESULT, result);

                if (result != LoginStatus.LOGIN_DONE) return ERROR;
                M.log(TAG, "login done");
            }

            RefreshDBPrefs.setStatus(RefreshStatus.REFRESHING_O,
                    context);
            result = UpdateAvgAtnd.update(crawlerDelegate, context);
            M.log(TAG, "UpdateAvgAtnd result" + result);
            broadcastResult(RefreshBroadcasts.BROADCAST_UPDATE_AVG_ATND_RESULT, result);
            if (result == UpdateAvgAtnd.ERROR) return ERROR;

            RefreshDBPrefs.setRecentlyUpdatedTagVisibility(true, context); //"Recently updated" is marked on subject with changed attendance.


            RefreshDBPrefs.setStatus(RefreshStatus.REFRESHING_D,
                    context);
            result = UpdateDetailedAttendance.start(crawlerDelegate, context);
            broadcastResult(RefreshBroadcasts.BROADCAST_UPDATE_DETAILED_ATTENDENCE_RESULT, result);
            if (result == UpdateDetailedAttendance.ERROR) return ERROR;

            manageAlarmService();       //For auto refresh.

            RefreshDBPrefs.setStatus(RefreshStatus.REFRESHING_DATESHEET,
                    context);
            updateDatesheet(crawlerDelegate);  //Broadcast and error checking is not done for datesheet as it is not that necessary.


            RefreshDBPrefs.setRefreshEndTimestamp(context);
            return OK;

        } finally {

            RefreshDBPrefs.setStatus(RefreshStatus.STOPPED, context);
            RefreshDBPrefs.setFirstRefreshOver(context);    //Indented to call only when it is first refresh. But calling it every time doesn't harm.
            crawlerDelegate.reset();

            ServiceRefreshTimetable.runIfNotRunning(context); //Start refresh timetable.
            NotificationManager.manageNotificaiton(context);
        }


    }


    private void updateDatesheet(CrawlerDelegate crawlerDelegate) {
        M.log(TAG, "UpdateDatesheet");
        if (RefreshDBPrefs.isFirstRefresh(context))
            DSSPManager.updateDataDontNotify(crawlerDelegate, context);
        else
            DSSPManager.updateDataAndNotify(crawlerDelegate, context);
    }


    private void manageAlarmService() {
        if (RefreshDBPrefs.isFirstRefresh(context))
            context.startService(new Intent(context, AutoRefreshAlarmService.class).putExtra(
                    AutoRefreshAlarmService.CALLER_TYPE, AutoRefreshAlarmService.INSTALLATION_DONE));
    }

    //Broadcast result of every step of DB initialization, so that UI elements can act accordingly.
    private void broadcastResult(String  type, int result) {

        if (type.equals(RefreshBroadcasts.BROADCAST_LOGIN_RESULT)
                && (result == LoginStatus.INVALID_PASS || result == LoginStatus.ACCOUNT_LOCKED)) {
            RefreshDBPrefs.setPasswordOutdated(context);
        } else if (refreshType == MANUAL_REFRESH) {
            //Not done in case of Auto refresh because we won't like to show a error dialog( ex. connectivity lost)
            // for refresh of which user is not even aware of.
            RefreshDbErrorDialogStore.store(type, result, context);
        }

        Intent intent = new Intent(type).putExtra(type, result);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }

} public class LoginStatus {
    public static final int LOGIN_DONE = 1;
    public static final int CONN_ERROR = 2;
    public static final int INVALID_PASS = 3;
    public static final int INVALID_ENROLL = 4;
    public static final int ACCOUNT_LOCKED = 5;
    public static final int UNKNOWN_ERROR = 6;

    public static  String responseToString(Context context,int response) {
        switch (response) {

        case INVALID_PASS:
                return context.getString(R.string.invalid_pass);

        case INVALID_ENROLL:
            return context.getString(R.string.invalid_enroll);

        case CONN_ERROR:
            return context.getString(R.string.con_error);
        case ACCOUNT_LOCKED :
                return context.getString(R.string.webkiosk_account_locked_at_first_login);

        case UNKNOWN_ERROR:
            return context.getString(R.string.unknown_error);

        default:
            return null;

        }
    }
} public class ServiceRefreshAll extends IntentService {
    public static final String TAG = "ServiceRefresh";
    public static final String RECREATING_DATABASE = "recreateDatabase";

    int refreshType;    //Manual refresh or auto refresh.

    public ServiceRefreshAll() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        refreshType = intent.getExtras().getInt(RefreshFullDB.REFRESH_TYPE);

        RefreshFullDB refreshFullDB = new RefreshFullDB(refreshType, this);

        try {
            refreshFullDB.refresh();
        } catch (SubjectChangedException e) {
            recreateDatabase(); //Sem has changed, recreate complete database.
        }
    }

    /**
     * Completely recreate all database.
     */
    public void recreateDatabase() {
        resetPrefs();
        LogoutActivity.unallocateRecource(this);
        TimetableCreateRefresh.deleteTimetableDb(this);
        LogoutActivity.deleteAttendence(this);
        if (isAutoRefresh()) {
            startServiceLogin();    //No need to show UI.
        } else
            startLoginActivity(); //Need to show UI.

    }


    private void resetPrefs() {

        String autoUpdateOver = getSharedPreferences(MainPrefs.PREFS_NAME, 0)
                .getString(AutoRefreshAlarmService.PREF_AUTO_UPDATE_OVER, "anyNetwork");
        String batch = MainPrefs.getBatch(this);
        String colg = MainPrefs.getColg(this);
        String userName = MainPrefs.getUserName(this);
        String enroll = MainPrefs.getEnroll(this);
        String pass = MainPrefs.getPassword(this);
        String dob = MainPrefs.getDOB(this);
        String fileName = MainPrefs.getOnlineTimetableFileName(this);
        MainPrefs.close();
        getSharedPreferences(MainPrefs.PREFS_NAME, 0).edit().clear()
                .commit();

        SharedPreferences.Editor ed = getSharedPreferences(MainPrefs.PREFS_NAME, 0).edit();
        ed.putString(AutoRefreshAlarmService.PREF_AUTO_UPDATE_OVER, autoUpdateOver);
        ed.putString(MainPrefs.BATCH, batch);
        ed.putString(MainPrefs.COLG, colg);
        ed.putString(MainPrefs.USER_NAME, userName);
        ed.putString(MainPrefs.ENROLL_NO, enroll);
        ed.putString(MainPrefs.PASSWORD, pass);
        ed.putString(MainPrefs.DOB, dob);
        ed.putBoolean(MainPrefs.IS_FIRST_TIME, false);
        ed.commit();
        MainPrefs.setOnlineTimetableFileName(this, fileName);

    }

    //Recreate full database using the flow from actual login flow.
    private void startLoginActivity() {
        Intent intent = new Intent(this, LoginActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(RECREATING_DATABASE, true);
        getApplication().startActivity(intent);

    }

    private boolean isAutoRefresh() {
        return refreshType == RefreshFullDB.AUTO_REFRESH;
    }

    private void startServiceLogin() {
        Intent intent = ServiceAppLogin.getIntent(MainPrefs.getColg(this),
                MainPrefs.getEnroll(this), MainPrefs.getPassword(this),
                MainPrefs.getBatch(this), MainPrefs.getDOB(this), this);
        startService(intent);
    }

    /**
     * Anyone starting this service is expected to pass intent returned by this function.
     */
    public static Intent getIntent(int refreshType, Context context) {
        Intent intent = new Intent(context, ServiceRefreshAll.class);
        intent.putExtra(RefreshFullDB.REFRESH_TYPE, refreshType);
        return intent;
    }
} public class BaseDrawerAdapter extends ArrayAdapter<String> {
    private ArrayList<String> objects;
    Context context;


    public BaseDrawerAdapter(Context context, int textViewResourceId, ArrayList<String> objects) {
        super(context, textViewResourceId, objects);
        this.objects = objects;
        this.context = context;
    }


    public View getView(int position, View convertView, ViewGroup parent) {
        View v;

        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.drawer_row, null);


        String data = objects.get(position);

        if (data != null) {
            TextView textView = (TextView) v.findViewById(R.id.drawer_text);
            if (textView != null) {
                textView.setText(data);
            }

            if (data.equals(context.getString(R.string.notification_view)) && LocalData.isShowNotificationAlert(context)) { //Show red alert in drawer if any notification is published by developers.
                ((ImageView) v.findViewById(R.id.drawer_alert)).setVisibility(View.VISIBLE);
            }
        }

        return v;
    }
} public class NetworkUtils {
    public static boolean isDataPackAvailable(Context context) {
        NetworkInfo networkInfo = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        return (networkInfo != null && networkInfo.isConnectedOrConnecting() && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
    }

    public static boolean isWifiAvailable(Context context) {
        NetworkInfo networkInfo = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        return (networkInfo != null && networkInfo.isConnectedOrConnecting() && networkInfo.getType() == ConnectivityManager.TYPE_WIFI);
    }

    public static boolean isInternetAvailable(Context context) {
        ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        return (networkInfo != null && networkInfo.isConnected());
    }
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.text.format.DateUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;
import com.blackMonster.notifications.NotificationManager;
import com.blackMonster.webkiosk.SharedPrefs.MainPrefs;
import com.blackMonster.webkiosk.controller.RefreshBroadcasts;
import com.blackMonster.webkiosk.controller.RefreshStatus;
import com.blackMonster.webkiosk.ui.Dialog.RefreshDbErrorDialogStore;
import com.blackMonster.webkiosk.ui.Dialog.ChangePasswordDialog;
import com.blackMonster.webkiosk.ui.Dialog.SetDOBDialog;
import com.blackMonster.webkiosk.utils.M;
import com.blackMonster.webkiosk.SharedPrefs.RefreshDBPrefs;
import com.blackMonster.webkiosk.controller.RefreshFullDB;
import com.blackMonster.webkiosk.crawler.LoginStatus;
import com.blackMonster.webkiosk.services.ServiceRefreshAll;
import com.blackMonster.webkiosk.ui.adapters.BaseDrawerAdapter;
import com.blackMonster.webkiosk.utils.NetworkUtils;
import com.blackMonster.webkioskApp.R;
import com.google.analytics.tracking.android.EasyTracker;
import java.util.ArrayList;
package com.blackMonster.webkiosk.ui;




public class BaseActivity extends AppCompatActivity {
    private String TAG = "BaseActivity";
    public LinearLayout activityContent = null; //Any activity extending BaseActivity have to  put all it's UI here.
    public boolean isReceiverRegistered = false;

    private boolean openDrawerWithIcon = true; //Sets if drawer could be opened with tap on icon on top left.
    private boolean isOptionsMenuLoaded = false;
    private boolean showRefreshAnimation = false;
    private ActionBarDrawerToggle mDrawerToggle;
    private boolean isRefreshBtnAnimated = false;
    private Menu actionbarMenu = null;
    private BaseDrawerAdapter drawerAdapter;