1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use jpreprocess_njd::NJDNode;

use crate::limit::Limit;

use super::*;

pub struct AccentPhrase {
    accent: usize,
    is_interrogative: bool,
    pub words: Vec<Word>,
}

impl AccentPhrase {
    pub fn new(start_node: &NJDNode) -> Self {
        Self {
            accent: start_node.get_acc().try_into().unwrap(),
            is_interrogative: false,
            words: vec![start_node.into()],
        }
    }
    pub(super) fn push_node(&mut self, node: &NJDNode) {
        if !matches!(node.get_chain_flag(), Some(true)) {
            panic!("push_node of AccentPhrase should not be called unless chain flag is true");
        }
        self.words.push(node.into());
    }
    pub(super) fn set_interrogative(&mut self) {
        self.is_interrogative = true;
    }

    pub fn to_e(&self, is_prev_pause: Option<bool>) -> String {
        let mora_count = self.count_mora();
        format!(
            "/E:{}_{}!{}_xx-{}",
            Limit::M.ulimit(mora_count),
            Limit::M.ulimit(if self.accent == 0 {
                mora_count
            } else {
                self.accent
            }),
            if self.is_interrogative { 1 } else { 0 },
            match is_prev_pause {
                Some(false) => "1",
                Some(true) => "0",
                None => "xx",
            }
        )
    }
    pub fn to_f(
        &self,
        accent_phrase_count_in_breath_group: usize,
        accent_phrase_index_in_breath_group: usize,
        mora_count_in_breath_group: usize,
        mora_index_in_breath_group: usize,
    ) -> String {
        let mora_count = self.count_mora();
        format!(
            "/F:{}_{}#{}_xx@{}_{}|{}_{}",
            Limit::M.ulimit(mora_count),
            Limit::M.ulimit(if self.accent == 0 {
                mora_count
            } else {
                self.accent
            }),
            if self.is_interrogative { 1 } else { 0 },
            Limit::M.ulimit(accent_phrase_index_in_breath_group + 1),
            Limit::M
                .ulimit(accent_phrase_count_in_breath_group - accent_phrase_index_in_breath_group),
            Limit::L.ulimit(mora_index_in_breath_group + 1),
            Limit::L.ulimit(mora_count_in_breath_group - mora_index_in_breath_group),
        )
    }
    pub fn to_g(&self, is_next_pause: Option<bool>) -> String {
        let mora_count = self.count_mora();
        format!(
            "/G:{}_{}%{}_xx_{}",
            Limit::M.ulimit(mora_count),
            Limit::M.ulimit(if self.accent == 0 {
                mora_count
            } else {
                self.accent
            }),
            if self.is_interrogative { 1 } else { 0 },
            match is_next_pause {
                Some(false) => "1",
                Some(true) => "0",
                None => "xx",
            }
        )
    }

    pub fn generate_mora_a(&self) -> Vec<String> {
        let mora_count = self.count_mora();
        let accent = if self.accent == 0 {
            mora_count
        } else {
            self.accent
        };
        (0..mora_count)
            .map(|mora_index| {
                format!(
                    "/A:{}+{}+{}",
                    Limit::M.ilimit(mora_index as isize - accent as isize + 1),
                    Limit::M.ulimit(mora_index + 1),
                    Limit::M.ulimit(mora_count - mora_index)
                )
            })
            .collect()
    }

    pub fn count_mora(&self) -> usize {
        self.words.iter().map(|word| word.count_mora()).sum()
    }
}