import os
from pathlib import Path

from tqdm import tqdm
from bs4 import BeautifulSoup
import xml.etree.ElementTree as ElT
import pandas as pd

from ml_editor.data_processing import format_raw_df, add_v1_features
from ml_editor.model_v2 import add_v2_text_features


def generate_model_text_features(raw_df_path, save_path=None):
    """
    Funkcja generująca cechy dla drugiego modelu i zapisująca je na dysku.
    Wyliczenie cech trwa kilka minut.
    :param raw_df_path: nazwa pliku zawierającego surowe dane DataFrame (wygenerowane za pomocą
    :param save_path: nazwa pliku, w którym mają być zapisane przetworzone dane DataFrame
    :return: przetworzone dane DataFrame
    """
    df = pd.read_csv(raw_df_path)
    df = format_raw_df(df.copy())
    df = df.loc[df["is_question"]].copy()
    df["full_text"] = df["Title"].str.cat(df["body_text"], sep=" ", na_rep="")

    df = add_v1_features(df.copy())
    df = add_v2_text_features(df.copy())

    if save_path:
        df.to_csv(save_path)
    return df


def parse_xml_to_csv(path, save_path=None):
    """
    Otwarcie zrzutu XML z wpisami, przekształcenie go do formatu CSV i wyodrębnienie tokenów.
    :param path: ścieżka do dokumentu XML zawierającego wpisy
    :return: obiekt DataFrame zawierający przetworzony tekst.
    """

    # Analiza pliku XML za pomocą standardowej biblioteki Pythona.
    doc = ElT.parse(path)
    root = doc.getroot()

    # Każdy wiersz zawiera osobne pytanie.
    all_rows = [row.attrib for row in root.findall("row")]

    # Wyświetlenie postępów za pomocą modułu tqdm, ponieważ przetwarzanie zajmuje trochę czasu.
    for item in tqdm(all_rows):
        # Wyodrębnienie tekstu z kodu HTML.
        soup = BeautifulSoup(item["Body"], features="html.parser")
        item["body_text"] = soup.get_text()

    # Utworzenie obiektu DataFrame na podstawie listy słowników.
    df = pd.DataFrame.from_dict(all_rows)
    if save_path:
        df.to_csv(save_path)
    return df


def get_data_from_dump(site_name, load_existing=True):
    """
    Załadowanie pliku XML, przekształcenie w CSV, serializowane i zwrócenie.
    :param load_existing: flaga oznaczająca załadowanie istniejących wyodrębnionych danych lub wygenerowanie nowych
    :param site_name: nazwa strony Stack Exchange
    :return: obiekt pandas DataFrame zawierający przetworzone dane XML
    """
    data_path = Path("data")
    dump_name = "%s.stackexchange.com/Posts.xml" % site_name
    extracted_name = "%s.csv" % site_name
    dump_path = data_path / dump_name
    extracted_path = data_path / extracted_name

    if not (load_existing and os.path.isfile(extracted_path)):
        all_data = parse_xml_to_csv(dump_path)
        all_data.to_csv(extracted_path)
    else:
        all_data = pd.DataFrame.from_csv(extracted_path)

    return all_data
