from features.base_feature import BaseFeature
import pandas as pd
from features.get_dtype import get_csv_dtype


class Os(BaseFeature):

    def get_loadcols(self):
        cols = [
            "Platform",
            "OsVer",
            "OsBuild",
            "OsPlatformSubRelease",
            "OsBuildLab",
            "Census_OSVersion",
            "Census_OSArchitecture",
            "Census_OSBranch",
            "Census_OSBuildNumber",
            "Census_OSBuildRevision"
        ]
        return cols

    def extract(self):
        return super().extract()

    def isServer(self, df):
        df["isServer"] = (df["Platform"] == "windows2016")
        return df[["MachineIdentifier", "isServer"]]

    def OSBuildNumber(self, df):
        col = df.columns[1]
        if col == "OsBuildLab":
            df = self.__OSBuildLab_spliter(df)
            s = "OBL_OsBuild"
        elif col == "Census_OSVersion":
            df = self.__Census_OSVersion_spliter(df)
            s = "OSV_OSBuildNumber"
        return df[["MachineIdentifier", "{}".format(s)]]

    def OSBuildRevision(self, df):
        col = df.columns[1]
        if col == "OsBuildLab":
            df = self.__OSBuildLab_spliter(df)
            s = "OBL_OsBuildRevision"
        elif col == "Census_OSVersion":
            df = self.__Census_OSVersion_spliter(df)
            s = "OSV_OSBuildRevision"
        return df[["MachineIdentifier", "{}".format(s)]]

    def OSArchitecture_CountEncoding(self, df):
        df = self.__OSBuildLab_spliter(df)
        train_df = self.__OSBuildLab_spliter(self.load_train()[["MachineIdentifier", "OsBuildLab"]])

        value_counts = train_df["OBL_OsArchitecture"].value_counts()

        df["OBL_OsArchitecture"] = df["OBL_OsArchitecture"].map(value_counts.to_dict()).fillna(1)
        return df[["MachineIdentifier", "OBL_OsArchitecture"]]

    def OSBranch_CountEncoding(self, df):
        df = self.__OSBuildLab_spliter(df)
        train_df = self.__OSBuildLab_spliter(self.load_train()[["MachineIdentifier", "OsBuildLab"]])

        value_counts = train_df["OBL_OsBranch"].value_counts()

        df["OBL_OsBranch"] = df["OBL_OsBranch"].map(value_counts.to_dict()).fillna(1)
        return df[["MachineIdentifier", "OBL_OsBranch"]]

    def OSBuildDate(self, df):
        df = self.__OSBuildLab_spliter(df)
        df["OBL_BuildDate"] = df["OBL_BuildDate"].str[:6] + df["OBL_BuildDate"].str[7:]
        df["OBL_BuildDate"] = df["OBL_BuildDate"].astype("int64")
        return df[["MachineIdentifier", "OBL_BuildDate"]]

    def OSBuildDate_Year(self, df):
        df = self.__OSBuildLab_spliter(df)
        df["OBL_BuildDate_Year"] = df["OBL_BuildDate"].str.slice(start=-11, stop=-9)
        df["OBL_BuildDate_Year"] = df["OBL_BuildDate_Year"].astype("int16")
        return df[["MachineIdentifier", "OBL_BuildDate_Year"]]

    def OSBuildDate_Month(self, df):
        df = self.__OSBuildLab_spliter(df)
        df["OBL_BuildDate_Month"] = df["OBL_BuildDate"].str.slice(start=-9, stop=-7)
        df["OBL_BuildDate_Month"] = df["OBL_BuildDate_Month"].astype("int8")
        return df[["MachineIdentifier", "OBL_BuildDate_Month"]]

    def OsVer_CountEncoding(self, df):
        df = self.__Census_OSVersion_spliter(df)
        train_df = self.__Census_OSVersion_spliter(self.load_train()[["MachineIdentifier", "Census_OSVersion"]])

        value_counts = train_df["OSV_OsVer"].value_counts()

        df["OSV_OsVer"] = df["OSV_OsVer"].map(value_counts.to_dict()).fillna(1)
        return df[["MachineIdentifier", "OSV_OsVer"]]

    def __OSBuildLab_spliter(self, df):
        col = ["OBL_{}".format(s) for s in ["OsBuild", "OsBuildRevision", "OsArchitecture", "OsBranch", "BuildDate"]]
        temp = df["OsBuildLab"].str.replace(r"*", r".").str.split(".", expand=True)
        temp.columns = col
        for c in col:
            df[c] = temp[c]

        # for Nan values
        full_df = self.load_full()
        full_df = full_df.set_index("MachineIdentifier")
        null_df = df[df["OsBuildLab"].isnull()]
        temp = df.set_index("MachineIdentifier")
        for m_id in null_df["MachineIdentifier"].values.tolist():
            temp.loc[m_id, "OBL_OsBuild"] = full_df.loc[m_id, "OsBuild"]
            temp.loc[m_id, "OBL_OsBuildRevision"] = full_df.loc[m_id, "Census_OSBuildRevision"]
            temp.loc[m_id, "OBL_OsBranch"] = full_df.loc[m_id, "Census_OSBranch"]
            temp.loc[m_id, "OBL_BuildDate"] = temp["OBL_BuildDate"].mode()[0]
        temp = temp.reset_index()
        df[col] = temp[col]
        df = df.astype({col[0]: "int16", col[1]: "int16", col[2]: "str", col[3]: "str", col[4]: "str"})
        return df

    def __Census_OSVersion_spliter(self, df):
        col = ["OSV_{}".format(s) for s in ["OsVer1", "OsVer2", "OSBuildNumber", "OSBuildRevision"]]
        temp = df["Census_OSVersion"].str.split(".", expand=True)
        temp.columns = col
        temp = temp.astype({col[0]: "str", col[1]: "str", col[2]: "int16", col[3]: "int32"})
        for c in col:
            df[c] = temp[c]
        df["OSV_OsVer"] = df["OSV_OsVer1"] + "." + df["OSV_OsVer2"]
        del df["OSV_OsVer1"], df["OSV_OsVer2"]
        return df
