from .BasicGenerator import BasicGenerator, PageSize
from docx.shared import Inches, RGBColor, Pt, Cm
from CivilTools.YDBLoader.BuildingDefine.StairPart import (
    Position,
    StairPart,
    LoadParams,
    StairLoad,
    LoadCalulateType,
)
from .UtilFunctions import MatrixSolver
from .DocTable import DocTable
from .DocPicture import DocPicture
from .DocParagraph import DocParagraph


class StairCalculationReport(BasicGenerator):
    def __init__(self):
        super().__init__()
        # 修改为A3图纸，横向，两栏
        self.change_paper_size(PageSize.A4)
        # 修改纸张Margin，单位mm
        self.change_paper_margin(20, 20, 20, 20)
        # 格式统一修改
        # self.body_style.paragraph_format.line_spacing = Pt(22)
        self.set_const()

    def set_const(self):
        self.big_title = "现浇板式普通楼梯设计"
        self.operate_code_title = "执行规范："
        self.operate_code_text_list = [
            "《混凝土结构通用规范》(GB 55008-2021)，本文简称《混凝土通用规范》；",
            "《混凝土结构设计规范》(GB 50010-2010(2015年版))，本文简称《混凝土规范》；",
            "《工程结构通用规范》(GB 55001-2021)；",
            "《建筑结构荷载规范》(GB 50009-2012)，本文简称《荷载规范》；",
        ]
        self.symbol_explain = "钢筋：d-HPB300；D-HRB335；E-HRB400；F-RRB400；G-HRB500；Q-HRBF400；R-HRB550"
        self.cut_line = "---------------------------------------------------------------------------------------------"
        self.concrete_data = {
            30: [14.3, 1.43, 2.01, 30000],  # // fc, ft, ftk, E
            35: [16.7, 1.57, 2.20, 31500],  # // fc, ft, ftk, E
            40: [19.1, 1.71, 2.39, 32500],  # // fc, ft, ftk, E
        }
        self.concrete_density = 25
        self.rebar_level = "HRB400"
        self.rebar_fy = 360
        self.indent = 0.22
        self.normal_font_size = 11

    # 数据入口！！！！
    def set_stair_data(self):
        """这个函数需要重写！！！！！是数据流入的最主要的入口"""
        position1 = Position(0, 2180, 0, 1910, 5030, 6850)
        sp1 = StairPart(position1, 13)
        sp1.left_thick = sp1.main_thick = sp1.right_thick = 130
        position2 = Position(0, 2180, 0, 1910, 5030, 6850)
        sp2 = StairPart(position2, 13)
        sp2.set_beam_offset(1, 500)
        position3 = Position(0, 2180, 0, 1910, 5030, 6850)
        sp3 = StairPart(position3, 13)
        sp3.set_beam_offset(2, 500)
        position4 = Position(0, 2180, 0, 1910, 5030, 6850)
        sp4 = StairPart(position4, 13)
        sp4.set_beam_offset(1, 500)
        sp4.set_beam_offset(2, 500)

        self.stair_list = [sp1, sp2, sp3, sp4]

    # 数据入口！！！！
    def set_calculate_info(self):
        self.load_param = LoadParams()
        self.concrete_level = 30
        self.rebar_area_adjust_coef = 1
        self.cover_thickness = 15

        self.displacement_limit = 200
        self.crack_width_limit = 0.3

    def load_calculate(self):
        left_dead = (
            self.current_stair.left_thick * self.concrete_density / 1000
            + self.load_param.append_dead_load
        )
        self.left_slab_load = StairLoad(
            left_dead, self.load_param.live_load, self.load_param
        )

        right_dead = (
            self.current_stair.right_thick * self.concrete_density / 1000
            + self.load_param.append_dead_load
        )
        self.right_slab_load = StairLoad(
            right_dead, self.load_param.live_load, self.load_param
        )

        main_dead = (
            self.current_stair.equivlent_main_slab_thick * self.concrete_density / 1000
            + self.load_param.append_dead_load
        )
        self.main_slab_load = StairLoad(
            main_dead, self.load_param.live_load, self.load_param
        )

    def do_the_math(self):
        solver = MatrixSolver(self.current_stair)
        solver.set_load(
            self.left_slab_load.q, self.main_slab_load.q, self.right_slab_load.q
        )
        self.current_stair.set_calculate_result(solver.submit_problem())

    def add_first_part(self):
        # 添加最大的标题
        self.add_big_title(self.big_title)
        # 添加一个2*6的表格，包含项目基本信息和设计人员信息
        table = DocTable(2, 6)
        table_context = [
            ["项目名称", "XX项目", "构件编号", "XXXX", "日    期", "2024/10/10"],
            ["设    计", "", "校    对", "", "审    核", ""],
        ]
        table.set_table_context(table_context)

        # table.no_grid = True
        table.all_bold = True
        self.add_table(table)
        # 添加执行规范和符号示意
        doc_par = DocParagraph(self.operate_code_title)
        doc_par.style = self.body_style
        doc_par.is_bold = True
        doc_par.font_size = 10
        doc_par.first_line_indent = 0
        self.add_paragraph(doc_par)

        for line in self.operate_code_text_list:
            doc_par = DocParagraph(line)
            doc_par.style = self.body_style
            doc_par.font_size = 10
            doc_par.first_line_indent = 0.22
            self.add_paragraph(doc_par)
        self.add_blank_paragraph()
        doc_par = DocParagraph(self.symbol_explain)
        doc_par.style = self.body_style
        doc_par.font_size = 10
        doc_par.first_line_indent = 0
        self.add_paragraph(doc_par)
        doc_par.context = self.cut_line
        self.add_paragraph(doc_par)

    def add_single_stair(self, stair: StairPart, index):
        self.current_stair = stair
        self.current_index = index

        # 添加一个标题
        doc_par = DocParagraph(
            f"{self.current_index}、{self.current_stair.stair_type}类梯板，标高区间：{self.current_stair.stair_elevation_range}"
        )
        doc_par.style = self.body_style
        doc_par.first_line_indent = 0
        doc_par.font_size = 11
        doc_par.is_bold = True
        doc_par.par_level = 1
        self.add_title(doc_par)

        # 进行必要的计算
        self.load_calculate()

        self.do_the_math()

        # 添加part1已知条件
        self.add_1_basic_info()
        self.add_2_load_and_calculate()
        self.add_3_result()
        self.add_blank_paragraph()

    def add_1_basic_info(self):
        stair = self.current_stair
        index = self.current_index
        indent = self.indent
        font_size = self.normal_font_size
        # 添加一个二级标题
        doc_par = DocParagraph(f"{index}.1 已知条件")
        doc_par.style = self.body_style
        doc_par.first_line_indent = 0
        doc_par.font_size = font_size
        doc_par.is_bold = False
        doc_par.par_level = 2
        self.add_title(doc_par)

        # 几何信息
        doc_par = DocParagraph("几何信息：")
        doc_par.style = self.body_style
        doc_par.first_line_indent = indent
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)

        doc_par = DocParagraph(
            f"左标高={stair.position.left_elevation/1000:.3f}m；右标高={stair.position.right_elevation/1000:.3f}m"
        )
        doc_par.style = self.body_style
        doc_par.first_line_indent = indent * 2
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)
        doc_par.context = f"左平台长度={stair.position.left_plat_length}mm；右平台长度={stair.position.right_plat_length}mm"
        self.add_paragraph(doc_par)
        doc_par.context = (
            f"左平台厚度={stair.left_thick}mm；右平台厚度={stair.right_thick}mm"
        )
        self.add_paragraph(doc_par)
        doc_par.context = f"内延长（左）={stair.beam_list[1].offset}mm；内延长（右）={stair.beam_list[2].offset}mm"
        self.add_paragraph(doc_par)
        doc_par.context = f"梯段长度={stair.position.right_x1 - stair.position.left_x2}mm；踏步数={stair.step_num}"
        doc_par.is_bold = True
        self.add_paragraph(doc_par)
        doc_par.context = f"梯板厚度={stair.main_thick}mm；梯段宽度={stair.stair_width}mm；梯井宽度={stair.stair_well_width}mm"
        self.add_paragraph(doc_par)
        doc_par.context = "平面类型：单跑"
        doc_par.is_bold = False
        self.add_paragraph(doc_par)
        self.add_blank_paragraph()

        # 荷载信息
        doc_par = DocParagraph("荷载信息：")
        doc_par.style = self.body_style
        doc_par.first_line_indent = indent
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)

        doc_par = DocParagraph(
            f"附加恒荷载={self.load_param.append_dead_load:.3f}kN/m^{{2}} 活荷载={self.load_param.live_load:.3f}kN/m^{{2}}"
        )
        doc_par.style = self.body_style
        doc_par.first_line_indent = indent * 2
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)
        doc_par.context = f"恒载分项系数：{self.load_param.dead_load_coef}；活载分项系数：{self.load_param.live_load_coef}；活载调整系数：γ_{{L}} ={self.load_param.live_load_adjust_coef:.2f}"
        self.add_paragraph(doc_par)
        doc_par.context = (
            f"活载准永久值系数：{self.load_param.live_load_permenent_coef}"
        )
        self.add_paragraph(doc_par)
        doc_par.context = f"混凝土等级：C{self.concrete_level}，f_{{c}} ={self.concrete_data[self.concrete_level][0]:.2f}MPa"
        self.add_paragraph(doc_par)
        doc_par.context = f"混凝土容重：{self.concrete_density:.2f}kN/mm^{{3}}"
        self.add_paragraph(doc_par)
        doc_par.context = f"配筋调整系数：{self.rebar_area_adjust_coef:.2f}；纵筋保护层厚度：c={self.cover_thickness}mm"
        self.add_paragraph(doc_par)
        doc_par.context = (
            f"梯板纵筋等级：{self.rebar_level}；f_{{y}} ={self.rebar_fy}MPa"
        )
        self.add_paragraph(doc_par)
        doc_par.context = (
            f"梯梁纵筋等级：{self.rebar_level}；f_{{y}} ={self.rebar_fy}MPa"
        )
        self.add_paragraph(doc_par)
        doc_par.context = (
            f"梯梁箍筋等级：{self.rebar_level}；f_{{y}} ={self.rebar_fy}MPa"
        )
        self.add_paragraph(doc_par)

        # 验算信息
        doc_par = DocParagraph("验算信息：")
        doc_par.style = self.body_style
        doc_par.first_line_indent = indent
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)

        doc_par = DocParagraph(
            f"挠度限值：L_{{0}} /{self.displacement_limit}；裂缝限值：{self.crack_width_limit}mm"
        )
        doc_par.style = self.body_style
        doc_par.first_line_indent = indent * 2
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)

        # 计算要求
        doc_par = DocParagraph("计算要求：")
        doc_par.style = self.body_style
        doc_par.first_line_indent = indent
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)

        doc_par = DocParagraph(
            "(1)楼梯板计算；(2)平台梁计算；(3)平台板裂缝验算；(4)平台板挠度验算；"
        )
        doc_par.style = self.body_style
        doc_par.first_line_indent = indent * 2
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)

    def add_2_load_and_calculate(self):
        index = self.current_index
        indent = self.indent
        font_size = self.normal_font_size
        # 添加一个二级标题
        doc_par = DocParagraph(f"{index}.2 荷载与内力计算")
        doc_par.style = self.body_style
        doc_par.first_line_indent = 0
        doc_par.font_size = font_size
        doc_par.is_bold = False
        doc_par.par_level = 2
        self.add_title(doc_par)

        doc_par = DocParagraph("(1)荷载计算：")
        doc_par.style = self.body_style
        doc_par.first_line_indent = 0
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)
        # 标准值
        doc_par.context = "标准值(qk)："
        doc_par.first_line_indent = indent
        self.add_paragraph(doc_par)
        doc_par.context = self.get_load_text(LoadCalulateType.qk)
        doc_par.first_line_indent = indent * 2
        self.add_paragraph(doc_par)
        # 设计值
        doc_par.context = "设计值(q)："
        doc_par.first_line_indent = indent
        self.add_paragraph(doc_par)
        doc_par.context = self.get_load_text(LoadCalulateType.q)
        doc_par.first_line_indent = indent * 2
        self.add_paragraph(doc_par)
        # 准永久值
        doc_par.context = "准永久值(qe)："
        doc_par.first_line_indent = indent
        self.add_paragraph(doc_par)
        doc_par.context = self.get_load_text(LoadCalulateType.qe)
        doc_par.first_line_indent = indent * 2
        self.add_paragraph(doc_par)

        doc_par.context = "(2)内力计算："
        doc_par.first_line_indent = 0
        self.add_paragraph(doc_par)
        # 标准值
        doc_par.context = "a.楼梯板：矩阵位移法求解。"
        doc_par.first_line_indent = indent
        self.add_paragraph(doc_par)

        self.add_blank_paragraph()

    def get_load_text(self, type: LoadCalulateType):
        if type == LoadCalulateType.qk:
            Q1 = self.left_slab_load.qk
            Q2 = self.main_slab_load.qk
            Q3 = self.right_slab_load.qk
        elif type == LoadCalulateType.q:
            Q1 = self.left_slab_load.q
            Q2 = self.main_slab_load.q
            Q3 = self.right_slab_load.q
        elif type == LoadCalulateType.qe:
            Q1 = self.left_slab_load.qe
            Q2 = self.main_slab_load.qe
            Q3 = self.right_slab_load.qe
        else:
            Q1 = Q2 = Q3 = 0

        if self.current_stair.stair_type == "AT":
            return f"斜梯段：{Q2:.2f}kN/m"
        elif self.current_stair.stair_type == "BT":
            return f"左延伸段：{Q1:.2f}kN/m\t斜梯段：{Q2:.2f}kN/m"
        elif self.current_stair.stair_type == "CT":
            return f"斜梯段：{Q2:.2f}kN/m\t右延伸段：{Q3:.2f}kN/m"
        elif self.current_stair.stair_type == "DT":
            return (
                f"左延伸段：{Q1:.2f}kN/m\t斜梯段：{Q2:.2f}kN/m\t右延伸段：{Q3:.2f}kN/m"
            )
        else:
            return "未知踏步类型，暂无数据"

    def add_3_result(self):
        index = self.current_index
        indent = self.indent
        font_size = self.normal_font_size
        # 添加一个二级标题
        doc_par = DocParagraph(f"{index}.3 计算结果")
        doc_par.style = self.body_style
        doc_par.first_line_indent = 0
        doc_par.font_size = font_size
        doc_par.is_bold = False
        doc_par.par_level = 2
        self.add_title(doc_par)

        doc_par = DocParagraph("计算说明：")
        doc_par.style = self.body_style
        doc_par.first_line_indent = 0
        doc_par.font_size = font_size
        self.add_paragraph(doc_par)

        doc_par.context = "(a)简化方法：取板沿着宽度方向单位长度的板带"
        doc_par.first_line_indent = indent
        self.add_paragraph(doc_par)

        doc_par.context = "(b)计算方法：矩阵位移法"
        self.add_paragraph(doc_par)

        doc_par.context = "单位说明："
        doc_par.first_line_indent = 0
        self.add_paragraph(doc_par)

        doc_par.context = "弯        矩：kN·m\t\t剪        力：kN/m\t\t挠        度：mm"
        doc_par.first_line_indent = indent
        self.add_paragraph(doc_par)
        doc_par.context = r"纵筋面积：mm^{2}/m\t\t截面尺寸：mm×mm\t\t裂        缝：mm"
        self.add_paragraph(doc_par)

        self.add_blank_paragraph()
        doc_par.context = "板段配筋计算结果："
        doc_par.first_line_indent = 0
        self.add_paragraph(doc_par)
        doc_par.context = "---------------------------------------------------------------------------------------------"
        self.add_paragraph(doc_par)

        self.insert_calculate_table()

        # self.insert_all_pictures()

        self.add_blank_paragraph()

    def insert_calculate_table(self):
        table_index = 1
        ft = self.concrete_data[self.concrete_level][1]
        if (
            self.current_stair.stair_type == "BT"
            or self.current_stair.stair_type == "DT"
        ):
            left_table = DocTable(8, 4)
            left_table.merge_cells(3, 1, 3, 3)
            left_table.set_table_title(
                f"计算板段-{table_index}(左延伸段)：截面B×H=1000mm×{self.current_stair.left_thick}mm"
            )
            moments = self.current_stair.get_left_slab_table_moments()
            shears = self.current_stair.get_left_slab_table_shears()
            shear_context = self.current_stair.get_shear_validate(
                "left", ft, self.cover_thickness
            )

            table_context = [
                ["截面位置", "左", "中", "右"],
                [
                    "弯矩(M)",
                    f"{moments[0]:.2f}",
                    f"{moments[1]:.2f}",
                    f"{moments[2]:.2f}",
                ],
                ["剪力(V)", f"{shears[0]:.2f}", f"{shears[1]:.2f}", f"{shears[2]:.2f}"],
                ["抗剪截面验算", shear_context],
                ["上部计算纵筋As'", "", "", ""],
                ["下部计算纵筋As", "", "", ""],
                ["上部纵筋实配", "", "", ""],
                ["下部纵筋实配", "", "", ""],
            ]
            left_table.set_table_context(table_context)
            self.add_table(left_table)
            table_index += 1

        cal_table = DocTable(13, 4)
        for i in [3, 8, 9, 11, 12]:
            cal_table.merge_cells(i, 1, i, 3)
        cal_table.set_table_title(
            f"计算板段-{table_index}(斜梯段)：截面B×H=1000mm×{self.current_stair.main_thick}mm"
        )
        moments = self.current_stair.get_main_table_moments()
        shears = self.current_stair.get_main_table_shears()
        shear_context = self.current_stair.get_shear_validate(
            "main", ft, self.cover_thickness
        )

        table_context = [
            ["截面位置", "左", "中", "右"],
            ["弯矩(M)", f"{moments[0]:.2f}", f"{moments[1]:.2f}", f"{moments[2]:.2f}"],
            ["剪力(V)", f"{shears[0]:.2f}", f"{shears[1]:.2f}", f"{shears[2]:.2f}"],
            ["抗剪截面验算", shear_context],
            ["上部计算纵筋As'", "", "", ""],
            ["下部计算纵筋As", "", "", ""],
            ["上部纵筋实配", "", "", ""],
            ["下部纵筋实配", "", "", ""],
            ["挠度限值", f"[f]={self.crack_width_limit:.2f}mm"],
            ["挠度验算结果", "满足"],
            ["裂缝宽度", "", "", ""],
            ["裂缝限值", f"[ω]={self.crack_width_limit:.2f}mm"],
            ["裂缝验算结果", ""],
        ]
        cal_table.set_table_context(table_context)
        self.add_table(cal_table)
        table_index += 1

        if (
            self.current_stair.stair_type == "CT"
            or self.current_stair.stair_type == "DT"
        ):
            right_table = DocTable(8, 4)
            right_table.merge_cells(3, 1, 3, 3)
            right_table.set_table_title(
                f"计算板段-{table_index}(右延伸段)：截面B×H=1000mm×{self.current_stair.right_thick}mm"
            )

            moments = self.current_stair.get_right_slab_table_moments()
            shears = self.current_stair.get_right_slab_table_shears()
            shear_context = self.current_stair.get_shear_validate(
                "right", ft, self.cover_thickness
            )

            table_context = [
                ["截面位置", "左", "中", "右"],
                [
                    "弯矩(M)",
                    f"{moments[0]:.2f}",
                    f"{moments[1]:.2f}",
                    f"{moments[2]:.2f}",
                ],
                ["剪力(V)", f"{shears[0]:.2f}", f"{shears[1]:.2f}", f"{shears[2]:.2f}"],
                ["抗剪截面验算", shear_context],
                ["上部计算纵筋As'", "", "", ""],
                ["下部计算纵筋As", "", "", ""],
                ["上部纵筋实配", "", "", ""],
                ["下部纵筋实配", "", "", ""],
            ]
            right_table.set_table_context(table_context)

            self.add_table(right_table)
            table_index += 1

    def create(self):
        self.add_first_part()
        for i in range(len(self.stair_list)):
            stair = self.stair_list[i]
            self.add_single_stair(stair, i + 1)
            if i < len(self.stair_list) - 1:
                self.add_page_break()

    def save_to_file(self, path):
        self.save(path)
