from typing import List
from typing import Dict
import logging


def decode_one_sequence_label_to_span(sequence_label: List[str]) -> List[Dict]:
    """
    对 BIO 序列进行解码成 List. 例如:

    ["B-Per", "I-Per", "O", "B-Loc"] ->
    [ {"label": "Per", "begin": 0, "end": 2},
      {"label": "Loc", "begin": 3, "end": 4} ]
    :param sequence_label: BIO 序列。
    :return: 解码好的字典列表
    """
    idel_state, span_state = 0, 1

    spans = list()
    begin = None
    tag = None

    state = idel_state
    for i, label in enumerate(sequence_label):

        if state == idel_state:
            if label[0] == "B":
                begin = i
                tag = label[2:]
                state = span_state
            elif label[0] == "O":
                pass
            elif label[0] == "I":
                logging.warning(f"{sequence_label} 有不满足 BIO 格式的问题")
            else:
                raise RuntimeError(f"{label} schema 不符合 BIO")

        elif state == span_state:
            if label[0] == "B":
                span = {"label": tag,
                        "begin": begin,
                        "end": i}
                spans.append(span)
                begin = i
                tag = label[2:]
                state = span_state
            elif label[0] == "O":
                span = {"label": tag,
                        "begin": begin,
                        "end": i}
                spans.append(span)
                begin = None
                tag = None
                state = idel_state
            elif label[0] == "I":
                state = span_state
            else:
                raise RuntimeError(f"{label} schema 不符合 BIO")
        else:
            raise RuntimeError(f"{state} 错误，应该是 在 [{idel_state}, {span_state}] ")

    if state == span_state:
        span = {"label": tag,
                "begin": begin,
                "end": len(sequence_label)}
        spans.append(span)

    return spans