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 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 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 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 TimetableCreateRefresh {
    public static final String TAG = "Timetable";

    public static final int ERROR_BATCH_UNAVAILABLE = -5;
    public static final int DONE = -123;
    public static final int TRANSFER_FOUND_DONE = -31;
    public static final int ERROR_DB_UNAVAILABLE = -4;
    public static final int ERROR_UNKNOWN = -3;
    public static final int ERROR_CONNECTION = -2;


    public static int createDatabase(List<SubjectAttendance> subjectLink,
                                     String colg, String enroll, String batch, Context context) {
        M.log("Timetable", "creartedatabse");
        int result;

        try {
            String ttFileName = getTimetableFileName(subjectLink, colg, context);

            if (ttFileName == null)
                result = DONE; // TIMETABLE NOT AVAILABLE
            else {
                M.log("Timetable", ttFileName);
                String newFileName = handleTimetableTransfers(ttFileName, colg,
                        enroll, batch, context);
                result = createTimetableDatabase(newFileName, colg, enroll, batch,
                        context);
                if (result == DONE && transferFound(ttFileName, newFileName))
                    result = TRANSFER_FOUND_DONE;
            }
        } catch (Exception e) {
            e.printStackTrace();
            result = ERROR_UNKNOWN;
        }

        return result;
    }

    public static void refresh(Context context) {

        String colg, enroll, batch, fileName;
        colg = MainPrefs.getColg(context);
        enroll = MainPrefs.getEnroll(context);
        batch = MainPrefs.getBatch(context);
        fileName = MainPrefs.getOnlineTimetableFileName(context);
        try {
            if (TimetableDbHelper.databaseExists(colg, enroll, batch,
                    fileName, context)) {
                M.log(TAG,
                        "imetableDataHelper.databaseExists(colg, enroll, batch, fileName, context)");
                String newFilename = handleTimetableTransfers(fileName, colg,
                        enroll, batch, context);
                if (transferFound(fileName, newFilename)) {
                    M.log(TAG, "transferFound(fileName, newFilename)");
                    CrawlerDelegate cd = new CrawlerDelegate(context);
                    cd.login(MainPrefs.getColg(context),
                            MainPrefs.getEnroll(context), MainPrefs.getPassword(context), MainPrefs.getDOB(context));
                    CreateDatabase.createFillTempAtndOverviewFromPreregSub(cd, context);
                    deleteTimetableDb(context);
                    createTimetableDatabase(newFilename, colg, enroll, batch,
                            context);
                }
            } else {
                List<SubjectAttendance> tmp = (List<SubjectAttendance>) (List<?>) (new AttendenceOverviewTable(context)).getAllSubjectAttendance();
                createDatabase(tmp, colg, enroll, batch,context);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void deleteTimetableDb(Context context) {
        String oldDbName = TimetableDbHelper.getDbNameThroughPrefs(context);
        TimetableDbHelper.shutdown();
        if (context.deleteDatabase(oldDbName)) {
            M.log(TAG, "database deleted");
            MainPrefs.setOnlineTimetableFileName(context, "NULL");
        }

    }

    public static boolean isError(int result) {
        return result == ERROR_BATCH_UNAVAILABLE
                || result == ERROR_UNKNOWN
                || result == ERROR_CONNECTION;
    }


    private static boolean transferFound(String f1, String f2) {
        if (f1 == null || f2 == null)
            return false;
        return !f1.equals(f2);
    }

    private static String handleTimetableTransfers(String ttFileName,
                                                   String colg, String enroll, String batch, Context context)
            throws Exception {
        M.log("Timetable", "handleTimetableTransfers");

        String finalFileName = ttFileName;
        BufferedReader transferList = FetchFromServer.getTransferList(colg,
                context);

        String newTtFileName = findTransfers(ttFileName, transferList);
        closeReader(transferList);
        if (newTtFileName != null) {
            finalFileName = newTtFileName;
            // createFillTempAtndOverviewFromPreregSub(context);

        }
        // /M.log("timetable", finalFileName);
        return finalFileName;

    }

    private static int createTimetableDatabase(String fileName, String colg,
                                               String enroll, String batch, Context context) {

        // /M.log(TAG, "loadTimetable");
        int result;

        if (!TimetableDbHelper.databaseExists(colg, enroll, batch, fileName,
                context)) {

            List<String> timetableDataList = new ArrayList<String>();
            result = FetchFromServer.getDataBundle(colg, fileName, batch,
                    timetableDataList, context);

            if (result == DONE) {
                TimetableTable.createDb(colg, fileName, batch, enroll, timetableDataList,
                        context);
                result = DONE;
            }


        } else {
            MainPrefs.setOnlineTimetableFileName(context, fileName);
            MainPrefs.setTimetableModified(context);
            result = DONE;

        }
        // /M.log(TAG, "load timetable  result : " + result);
//        if (result == FetchFromServer.DONE)
//            result = DONE;
        return result;
    }

    private static String getTimetableFileName(List<SubjectAttendance> subjectLink,
                                               String colg, Context context) throws Exception {
        // /M.log("Timetable", "getTimetableFileName");
        BufferedReader subCodeList = FetchFromServer.getSubcodeList(colg,
                context);
        String result = findMatch(subjectLink, subCodeList);
        closeReader(subCodeList);
        return result;

    }

    private static String findTransfers(String ttFileName,
                                        BufferedReader transferList) {
        // /M.log("Timetable", "findTransfers");

        try {
            if (!transferDatabaseExist(transferList))
                return null;

            while (true) {
                String line = transferList.readLine();
                if (line == null)
                    break;
                if (line.replaceAll("\\s", "").equals(""))
                    continue;
                if (line.substring(0, line.indexOf('$')).contains(ttFileName))
                    return line.substring(line.indexOf('$') + 1);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String findMatch(List<SubjectAttendance> subjectLink,
                                    BufferedReader subCodeList) {
        // /M.log("Timetable", "findMatch");

        if (subCodeList == null || subjectLink == null)
            return null;
        int size = subjectLink.size();

        int i;
        String line;
        try {
            if (!subCodeDatabaseExist(subCodeList))
                return null;
            while (true) {
                line = subCodeList.readLine();
                if (line == null)
                    break;
                if (line.replaceAll("\\s", "").equals(""))
                    continue;
                // / M.log("Timetable", line);

                int matched = 0;
                for (i = 0; i < size; ++i) {
                    if (line.contains(subjectLink.get(i).getSubjectCode().substring(1)))
                        ++matched;
                }

                if (matched >= (size / 2 + 1)) {
                    return line.substring(line.indexOf('$') + 1);
                }

            }
        } catch (Exception e) {
        }
        return null;
    }

    private static boolean transferDatabaseExist(BufferedReader transferList)
            throws IOException {
        if (transferList == null)
            return false;
        return transferList.readLine().contains("transfers");
    }

    private static boolean subCodeDatabaseExist(BufferedReader subCodeList)
            throws IOException {
        return subCodeList.readLine().contains("subjectCodes");
    }

    private static void closeReader(BufferedReader reader) {
        try {
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

} public class CrawlerDelegate {
    private String colg, enroll, pass;
    private Context context;


    private SiteLogin siteLogin;

    public CrawlerDelegate( Context context) {

        this.context = context;
    }


    public int login(String colg, String enroll, String pass, String dob) {
        this.colg = colg;
        this.enroll = enroll;
        this.pass = pass;
        siteLogin = new SiteLogin();
        return siteLogin.login(colg, enroll, pass, dob, context);
    }

    public void reset() {
        if (siteLogin != null) siteLogin.close();
        siteLogin = null;
    }


    SubjectAndStudentDetailsMain subjectAndStudentDetailsMain = null;

    /**
     * SubCode in SubjectAttendance is concatenated with "T"
     * "-1" for field where attendance is not available.
     */
    public List<SubjectAttendance> getSubjectAttendanceMain() throws Exception {
        if (subjectAndStudentDetailsMain == null)
            subjectAndStudentDetailsMain = new SubjectAndStudentDetailsMain(siteLogin.getConnection(), colg);


        return (List<SubjectAttendance>)(List<?>)subjectAndStudentDetailsMain.getSubjectInfo();
    }

    public String getStudentName() throws Exception {
        if (subjectAndStudentDetailsMain == null)
            subjectAndStudentDetailsMain = new SubjectAndStudentDetailsMain(siteLogin.getConnection(), colg);
        return subjectAndStudentDetailsMain.getStudentName();
    }

    /**
     * here average attendance data is kept "-1" i.e overall, lect, tute, pract.
     * SubCode in SubjectAttendance is concatenated with "T"
     * @return SubjectInfo
     * @throws Exception
     */
    public List<SubjectAttendance> getSubjectAttendanceFromPreReg() throws  Exception{
        return (List<SubjectAttendance>)(List<?>)new SubjectDetailsFromPreReg(siteLogin.getConnection(),colg).getSubjectInfo();
    }

    /**
     * here average attendance data is kept "-1" i.e overall, lect, tute, pract.
     * SubCode in SubjectAttendance is concatenated with "T"
     * @return SubjectInfo
     * @throws Exception
     */
    public List<SubjectAttendance> getSubjectAttendanceFromSubRegistered() throws  Exception{
        return (List<SubjectAttendance>)(List<?>)new SubjectDetailsFromSubReg(siteLogin.getConnection(),colg).getSubjectInfo();
    }

    public List<DetailedAttendance> getDetailedAttendance(String subCode) throws Exception{

        List<CrawlerSubjectInfo> crawlerSubInfos = (List<CrawlerSubjectInfo>)(List<?>) getSubjectAttendanceMain();

        CrawlerSubjectInfo crawlerSubInfo = findSubjectInfo(crawlerSubInfos, subCode);

        if (crawlerSubInfo == null || crawlerSubInfo.getLink() == null) return null;

        return new FetchDetailedAttendence(siteLogin.getConnection(),
                crawlerSubInfo.getLink(),crawlerSubInfo.isNotLab()).getAttendance();

    }


    public  List<DS_SP> getDateSheetSeatingPlan() throws Exception
    {
       return DSSPFetch.getData(siteLogin.getConnection(), colg, context);
    }



    private CrawlerSubjectInfo findSubjectInfo(List<CrawlerSubjectInfo> crawlerSubInfos, String subCode) {

        for (CrawlerSubjectInfo crawlerSubInfo : crawlerSubInfos) {

            if (crawlerSubInfo.getSubjectCode().equals(subCode)) return crawlerSubInfo;
        }

        return  null;
    }




} 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 AutoRefreshAlarmService extends IntentService {
	public static final String TAG = "serviceAlarm";
	public static final String PREF_AUTO_UPDATE_OVER = "pref_auto_update_over";
	public static final String CALLER_TYPE = "callerType";
	

	//Points at which this service is called.
	public static final int BOOT_COMPLETE = 1;
	public static final int CONNECTIVITY_CHANGE = 2;	//Network connectivity changed
	public static final int INSTALLATION_DONE = 3;
	public static final int TIME_JUNCTION = 4;
	
	public static final double LAST_SERVER_UPDATE_IN_DAY = 19;  ///i.e 7pm, time after which no teacher updates attendance. i.e time after which server will not be updated.
	public static final double WAIT_WIFI_UPTO = 22.5;
	

	public AutoRefreshAlarmService() {
		super(TAG);
	}

	@Override
	protected void onHandleIntent(Intent intent) {

		int callerType = intent.getExtras().getInt(CALLER_TYPE);

		switch (callerType) {
		
		case CONNECTIVITY_CHANGE:
			connectivityChange();
			break;
		case TIME_JUNCTION:
			timeJunciton();
			break;
		case BOOT_COMPLETE:	
			createRepeatingAlarm(WAIT_WIFI_UPTO);
			break;
		case INSTALLATION_DONE:
			createRepeatingAlarm(WAIT_WIFI_UPTO);
			break;
		}
	}

	private void timeJunciton() {
		if (RefreshDBPrefs.canAutoRefresh(this)) {
			
			if ( ! isRefreshedAfterServerUpdate() ) {
				if (isNetAvailableForApp()) {
					startRefreshService();
				}
			}
		
		}
		
	}

	private void connectivityChange() {
		
		if (RefreshDBPrefs.canAutoRefresh(this)) {
			if (isWifiAvailable()) {
				startRefreshService();
				//log ("refresh started");
			}
			else
			{
				if ( ! isWifiOnlyZone()) 
				{
					//log("not in wifiOnly zone");
					timeJunciton();
				}
			}
			
		}
	}
	
	private boolean isWifiOnlyZone() {
	//	log("last server updated time : " + printTime(getLastServerUpdatedTime()) + " wifi zone end time : " 
	//+ printTime(getWifiZoneEndTime()) );
		return System.currentTimeMillis() > getLastServerUpdatedTime() &&
				System.currentTimeMillis() < getWifiZoneEndTime() ; 
		
	}

	private void createRepeatingAlarm(double time) {
		
		//Log.d(TAG, "create repeating alarm");
		//log("creating repeatin alarm");
		Calendar calender = Calendar.getInstance();
		long randomize = calender.get(Calendar.MILLISECOND) +  calender.get(Calendar.SECOND) *1000 + calender.get(Calendar.MINUTE) * 60000;
		long timeJunction = getFutureTimeInMillisec(time) + randomize;
		RefreshDBPrefs.setWifiZoneEndRandomizeTime(randomize, this);
		//log ("current time " + printTime(System.currentTimeMillis()) + "  timejunction : " + printTime(timeJunction) + " random : " + randomize);
		
		
		setAlarm(timeJunction);
		
		
	}
	//beware using this funcion
	private void setAlarm(long timeJunction) {
		Intent intent = new Intent(this,AutoRefreshAlarmService.class);
		intent.putExtra("callerType", AutoRefreshAlarmService.TIME_JUNCTION);
		PendingIntent operation = PendingIntent.getService(this, -1,
				intent,PendingIntent.FLAG_CANCEL_CURRENT);
		

		AlarmManager am = ((AlarmManager) this.getSystemService(Context.ALARM_SERVICE));
		am.cancel(operation);
		am.setRepeating(AlarmManager.RTC, timeJunction
				, AlarmManager.INTERVAL_DAY, operation);		
	}
	
	public static  void cancelAlarm(Context context) {
		Intent intent = new Intent(context,AutoRefreshAlarmService.class);
		intent.putExtra("callerType", AutoRefreshAlarmService.TIME_JUNCTION);
		PendingIntent operation = PendingIntent.getService(context, -1,
				intent,PendingIntent.FLAG_CANCEL_CURRENT);
		
		
		AlarmManager am = ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE));
		am.cancel(operation);
				
	}

	private boolean isNetAvailableForApp() {
		boolean result = false;
		if (isWifiAvailable()) result = true;
		else 
		{
			if (isDataPackAvailable() && canUpdateOverDataPack()) result = true;
			else result = false;
		}
		
		return result;
	}

	private boolean canUpdateOverDataPack() {
		return getSharedPreferences(MainPrefs.PREFS_NAME, 0).getString(PREF_AUTO_UPDATE_OVER, "anyNetwork").equals("anyNetwork");
	}

	private boolean isDataPackAvailable() {
		NetworkInfo networkInfo = ( (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE) ).getActiveNetworkInfo();
		return (networkInfo != null && networkInfo.isConnected() && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
	}

	private boolean isWifiAvailable() {
		NetworkInfo networkInfo = ( (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE) ).getActiveNetworkInfo();
		return (networkInfo != null && networkInfo.isConnected() && networkInfo.getType() == ConnectivityManager.TYPE_WIFI);
		}
	
	
	private boolean isRefreshedAfterServerUpdate() {
		//Log.d(TAG, "isRefreshedAfterServerUpdate ");
		//log("isrefreshedAfterServerUpdate");
		
		
		long lastServerUpdatedTime = getLastServerUpdatedTime();
		
		printTime( System.currentTimeMillis());
		printTime ( lastServerUpdatedTime);
		
		//Log.d(TAG, "isRefreshedAfterServerUpdate : " + DateUtils.formatDateTime(this, lastServerUpdatedTime, DateUtils.FORMAT_SHOW_TIME) + 
	//			"  " + DateUtils.formatDateTime(this, lastServerUpdatedTime, DateUtils.FORMAT_SHOW_DATE));
		
		//log ( "last server updated till (ie 7pm) : " + printTime(lastServerUpdatedTime) );
		
		return RefreshDBPrefs.getRefreshEndTimeStamp(this) >  lastServerUpdatedTime ;
	}

	
	
		
	
	private long getLastServerUpdatedTime() {
		
		return getPastTimeInMillisec(LAST_SERVER_UPDATE_IN_DAY) ;		
	}
	
	private long getWifiZoneEndTime() {
		return getLastServerUpdatedTime() +( (long) ( ( WAIT_WIFI_UPTO - LAST_SERVER_UPDATE_IN_DAY ) * AlarmManager.INTERVAL_HOUR ) )+ 
				RefreshDBPrefs.getWifiZoneEndRandomizeTime(this);
	}
	
	private long getPastTimeInMillisec(double time) {
		Calendar calender = Calendar.getInstance();
		long  timeDiff=  ( calender.get(Calendar.HOUR_OF_DAY) * 60 + calender.get(Calendar.MINUTE) - 
				(long) (time *60) ) * 60 * 1000;
		if (timeDiff <0 ) timeDiff = AlarmManager.INTERVAL_DAY + timeDiff;
		return System.currentTimeMillis() - timeDiff;
	}
	
	private long getFutureTimeInMillisec(double time) {
		Calendar calender = Calendar.getInstance();
		long tm = (long) (time*60) ;
	//	Log.d(TAG, "tt " + tm);
		long  timeDiff= ( tm  - 
				calender.get(Calendar.HOUR_OF_DAY) * 60 - calender.get(Calendar.MINUTE) ) * 60 * 1000;
		if (timeDiff <0 ) timeDiff = AlarmManager.INTERVAL_DAY + timeDiff;
		return System.currentTimeMillis() + timeDiff ; 
		
	}

	private String printTime(long currentTimeMillis) {
		 SimpleDateFormat sdf = new SimpleDateFormat("MMM dd,yyyy HH:mm");

	        Date resultdate = new Date(currentTimeMillis);
	        String res = sdf.format(resultdate);
	     //   Log.d(TAG,  res );
	        return res;
	}

	private void startRefreshService() {
		Intent intent = ServiceRefreshAll.getIntent(RefreshFullDB.AUTO_REFRESH, this);

		startService(intent);
		
	}
	
	
	
} 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);
    }

}
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v4.content.LocalBroadcastManager;
import com.blackMonster.webkiosk.controller.RefreshBroadcasts;
import com.blackMonster.webkiosk.controller.RefreshStatus;
import com.blackMonster.webkiosk.utils.M;
import com.blackMonster.webkiosk.SharedPrefs.MainPrefs;
import com.blackMonster.webkiosk.SharedPrefs.RefreshDBPrefs;
import com.blackMonster.webkiosk.controller.Timetable.TimetableCreateRefresh;
import com.blackMonster.webkiosk.crawler.CrawlerDelegate;
import com.blackMonster.webkiosk.crawler.LoginStatus;
import com.blackMonster.webkiosk.services.AutoRefreshAlarmService;
import com.blackMonster.webkiosk.ui.Dialog.RefreshDbErrorDialogStore;
package com.blackMonster.webkiosk.controller.appLogin;



/**
 * Initializes database on first login of app.
 */
public class InitDB {

    public static final String BROADCAST_DATEBASE_CREATION_RESULT = "BROADCAST_DATEBASE_CREATION_RESULT";
    private static final String TAG = "InitDB";

    String enroll, pass, batch, colg, dob;
    Context context;

    CrawlerDelegate crawlerDelegate;


    public InitDB(String enroll, String pass, String batch, String colg, String dob, Context context) {
        this.enroll = enroll;
        this.pass = pass;
        this.batch = batch;
        this.colg = colg;
        this.dob = dob;
        this.context = context;
    }


    /*
     * TEMPLATE:
     *
     * RefreshDBPrefs.setStatus(..);
     * do work....
     * broadcastResult(..);
     * Error handling
     *
     * RefreshDBPrefs.setStatus(..);
     *      .
     *      .
     */

    public boolean start() {
        int result;

        try {
            RefreshDBPrefs.setStatus(RefreshStatus.LOGGING_IN, context);
            crawlerDelegate = new CrawlerDelegate(context);
            result = crawlerDelegate.login(colg, enroll, pass, dob);
            broadcastResult(RefreshBroadcasts.BROADCAST_LOGIN_RESULT, result);

            if (result != LoginStatus.LOGIN_DONE) return false;