"""
The functions from this file are reused to show plots in Jupyter notebook
abstracting code and only displaying plots in the notebook.
"""
import argparse
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import numpy as np
import os


def plot_radar_chart(df, graph_name):
    """
    Plots a radar chart based on the input DataFrame and saves the
    plot as a PNG file.

    Parameters:
    df (pandas.DataFrame): The input DataFrame. It should contain the
    following columns:
        'dlr_soft_class', 'howfairis_repository', 'howfairis_license',
        'howfairis_registry', 'howfairis_citation', 'howfairis_checklist'
    graph_name (str): The name of the output PNG file.

    Returns:
    None. A PNG file is saved in the current working directory.
    """
    # Check if necessary columns exist in the DataFrame
    necessary_columns = [
        'dlr_soft_class', 'howfairis_repository', 'howfairis_license',
        'howfairis_registry', 'howfairis_citation', 'howfairis_checklist'
    ]
    for column in necessary_columns:
        if column not in df.columns:
            print(f"Column '{column}' not found in the DataFrame.")
            return

    # Rename the columns
    df = df.rename(columns={
        'dlr_soft_class': 'DLR Class',
        'howfairis_repository': 'Opensource',
        'howfairis_license': 'License',
        'howfairis_registry': 'Registry',
        'howfairis_citation': 'Citation',
        'howfairis_checklist': 'Checklist'
    })

    # Convert boolean to int
    df[['Opensource', 'License', 'Registry', 'Citation', 'Checklist']] = df[
        ['Opensource', 'License', 'Registry', 'Citation', 'Checklist']
    ].astype(int)

    # Filter the DataFrame according to 'DLR Class' values
    df = df[df['DLR Class'].isin([0.0, 1.0, 2.0])]

    # Convert 'DLR Class' to integer
    df['DLR Class'] = df['DLR Class'].astype(int)

    # Select the specified columns and group by 'DLR Class'
    columns = ['DLR Class', 'Opensource', 'License', 'Registry',
               'Citation', 'Checklist']
    df = df[columns].groupby('DLR Class').mean().reset_index()

    # Plotting radar chart
    labels = df.columns[1:]
    num_vars = len(labels)

    angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
    angles += angles[:1]

    fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))

    for i, row in df.iterrows():
        values = row.drop('DLR Class').tolist()
        values += values[:1]
        label = f"DLR class {int(row['DLR Class'])}"  # Use class as label
        ax.plot(angles, values, label=label)
        ax.fill(angles, values, alpha=0.25)

    ax.set_yticklabels([])
    ax.set_xticks(angles[:-1])
    ax.set_xticklabels(labels)
    plt.legend(loc='upper right')
    plt.savefig(f'{graph_name}.png')
    plt.show()


def plot_documentation(df, file_path):
    """
    Plots a grouped bar chart based on the input
    DataFrame and saves the plot as a PNG file.

    Parameters:
    df (pandas.DataFrame): The input DataFrame.
    It should contain the following columns:
        'dlr_soft_class', 'readme_content',
        'quick_start_guide', 'help_commands'
    file_path (str): The full path of the output PNG file.

    Returns:
    None. A PNG file is saved in the specified path.
    """
    df = df[df['dlr_soft_class'].isin([0, 1, 2])]
    total_counts = df['dlr_soft_class'].value_counts()
    features = ['project_information', 'installation_instruction', 'usage_guide']
    feature_labels = ['Project Information', 'Installation Instructions', 'Usage Guide']

    percentages = [
        [
            (df[(df['dlr_soft_class'] == dlr_class) & (df[feature])].shape[0] /
             total_counts[dlr_class]) * 100 for feature in features
        ]
        for dlr_class in [0, 1, 2]
    ]

    bar_width = 0.2
    r = np.arange(len(features))
    colors = ['#87CEEB', '#4682B4', '#1E90FF']  # Shades of blue from sky-blue to dark blue

    for i in range(3):
        plt.bar(
            r + i * bar_width, percentages[i],
            color=colors[i],
            width=bar_width,
            edgecolor='black',  # Set edge color to black for a defined border
            linewidth=1.5,       # Optional: increase line width for visibility
            label=f'DLR Class {i}'
        )

    plt.ylabel('Percentage (%)', fontweight='bold')
    plt.xticks([r + bar_width for r in range(len(features))], feature_labels)
    plt.legend()

    os.makedirs(os.path.dirname(file_path), exist_ok=True)
    plt.savefig(file_path)
    plt.show()


def plot_stacked_bar_reuse(df, column_name, file_path, legend_title):
    """
    Plots a stacked bar chart based on the input DataFrame and saves
    the plot as a PNG file.

    Parameters:
    df (pandas.DataFrame): The input DataFrame. It should contain
    the following columns:
        'dlr_soft_class' and the column specified in column_name.
    column_name (str): The name of the column to calculate percentages for.
    file_path (str): The full path of the output PNG file.
    legend_title (str): The title for the legend.

    Returns:
    None. A PNG file is saved in the specified path.
    """
    # Calculate percentages of column_name presence for each 'dlr_soft_class'
    percentages = df.groupby('dlr_soft_class')[column_name].value_counts(
        normalize=True).unstack() * 100

    # Define custom blue shades for the 'Yes' and 'No' categories
    colors = ['#87CEEB', '#1E90FF']  # Light sky blue and darker blue for stacked sections

    # Plot the stacked bar chart with custom colors and edge color set to black
    ax = percentages.plot(
        kind='bar', stacked=True, color=colors, edgecolor='black', linewidth=1.5
    )

    # Set labels and title
    plt.xlabel('DLR Application Class')
    plt.ylabel('Percentage of Repositories')

    # Move legend outside the plot
    plt.legend(
        title=legend_title, labels=['No', 'Yes'],
        bbox_to_anchor=(1.05, 1), loc='upper left'
    )

    # Save the plot
    os.makedirs(os.path.dirname(file_path), exist_ok=True)
    plt.savefig(file_path, bbox_inches='tight')

    # Show the plot
    plt.show()


def plot_continuous_integration(df, file_path):
    """
    Plots a grouped bar chart based on the input DataFrame and
    saves the plot as a PNG file.

    Parameters:
    df (pandas.DataFrame): The input DataFrame. It should contain
      the following columns:
        'language', 'dlr_soft_class', 'continuous_integration',
        'add_test_rule', 'add_lint_rule'
    file_path (str): The full path of the output PNG file.

    Returns:
    None. A PNG file is saved in the specified path.
    """
    # Filter the DataFrame according to 'language' and 'dlr_soft_class' values
    df = df[df['language'].isin(['C++', 'Python', 'R']) &
            df['dlr_soft_class'].isin([0, 1, 2])]

    # Calculate the total count for each 'dlr_soft_class'
    total_counts = df['dlr_soft_class'].value_counts()

    # Percentage of True values for each column and 'dlr_soft_class'
    features = ['continuous_integration', 'add_test_rule', 'add_lint_rule']
    percentages = [
        [
            (df[(df['dlr_soft_class'] == dlr_class) & (df[feature])].shape[0] /
             total_counts[dlr_class]) * 100 for feature in features
        ]
        for dlr_class in [0, 1, 2]
    ]

    # Bar width
    bar_width = 0.2

    # Positions of the bars on the x-axis
    r = np.arange(len(features))

    # Define custom blue shades for each class
    colors = ['#87CEEB', '#4682B4', '#1E90FF']  # Light sky blue to dark blue

    # Create the grouped bar chart with specified colors and edge color set to black
    for i in range(3):
        plt.bar(
            r + i * bar_width, percentages[i],
            color=colors[i],
            width=bar_width,
            edgecolor='black',  # Set edge color to black for a defined border
            linewidth=1.5,       # Optional: increase line width for visibility
            label=f'Class {i}'
        )

    # Adding labels
    plt.ylabel('Percentage (%)', fontweight='bold')
    updated_labels = ['Continuous Integration', 'Linters in CI', 'Automated Testing']
    plt.xticks([r + bar_width for r in range(len(features))], updated_labels)

    # Adding the legend
    plt.legend()

    # Save the plot
    os.makedirs(os.path.dirname(file_path), exist_ok=True)
    plt.savefig(file_path, bbox_inches='tight')

    # Show the plot
    plt.show()


def plot_comment_start(df, file_path):
    """
    Plots a stacked bar chart based on the input DataFrame and
    saves the plot as a PNG file.

    Parameters:
    df (pandas.DataFrame): The input DataFrame.
    It should contain the following columns:
        'language', 'dlr_soft_class', 'comment_category'
    file_path (str): The full path of the output PNG file.

    Returns:
    None. A PNG file is saved in the specified path.
    """
    # Step 2: Filter Data by Language
    df = df[df['language'].isin(['Python', 'C++', 'R'])]

    # Replace 'none' with 'less' and ensure comment_category
    df['comment_at_start'] = df['comment_at_start'].replace('none', 'less')
    comment_order = ['less', 'some', 'more', 'most']
    df['comment_at_start'] = pd.Categorical(
        df['comment_at_start'],
        categories=comment_order,
        ordered=True
    )

    # Step 3: Prepare Data for Visualization

    # Create a pivot table for the stacked bar plot with percentages
    pivot_table = df.pivot_table(
        index='dlr_soft_class',
        columns='comment_at_start',
        aggfunc='size',
        fill_value=0
    )

    # Calculate the percentage
    pivot_table = pivot_table.div(pivot_table.sum(axis=1), axis=0) * 100

    # Step 4: Create Stacked Bar Plot with custom colors and black border
    plt.figure(figsize=(10, 6))
    colors = ['#87CEEB', '#4682B4', '#1E90FF', '#000080']  # Light sky blue to dark blue shades

    # Plot with custom colors and edge color set to black
    pivot_table.plot(
        kind='bar', stacked=True, color=colors, edgecolor='black', linewidth=1.5
    )

    # Set labels and title
    plt.xlabel('DLR Application Class')
    plt.ylabel('Percentage of Repositories')

    # Adjust legend position
    plt.legend(
        title='Files with comment at start',
        bbox_to_anchor=(1.05, 1),
        loc='upper left'
    )

    # Adjust layout and remove title
    plt.tight_layout()
    plt.title(None)

    # Save the plot
    os.makedirs(os.path.dirname(file_path), exist_ok=True)
    plt.savefig(file_path, bbox_inches='tight')

    # Show the plot
    plt.show()


def main():
    parser = argparse.ArgumentParser(description='Plotting tool for data analysis.')
    parser.add_argument('csv_file', type=str, help='Path to the input CSV file.')
    parser.add_argument(
        'plot_type',
        type=str,
        choices=[
            'radar', 'documentation', 'stacked_bar_reuse',
            'continuous_integration', 'comment_start'
        ],
        help='Type of plot to generate.'
    )

    parser.add_argument('output_file', type=str, help='Path to the output PNG file.')
    parser.add_argument(
        '--legend_title',
        type=str,
        default='',
        help='Title for the legend (only used for stacked_bar_reuse plot).'
    )
    args = parser.parse_args()

    df = pd.read_csv(args.csv_file)

    if args.plot_type == 'radar':
        plot_radar_chart(df, args.output_file)
    elif args.plot_type == 'documentation':
        plot_documentation(df, args.output_file)
    elif args.plot_type == 'stacked_bar_reuse':
        column_name = input("Enter the column name to calculate percentages for: ")
        plot_stacked_bar_reuse(df, column_name, args.output_file, args.legend_title)
    elif args.plot_type == 'continuous_integration':
        plot_continuous_integration(df, args.output_file)
    elif args.plot_type == 'comment_start':
        plot_comment_start(df, args.output_file)


if __name__ == "__main__":
    main()
