package com.nlf.calendar;

import com.nlf.calendar.util.LunarUtil;

import java.util.List;
import java.util.Map;

/**
 * 时辰
 *
 * @author 6tail
 */
public class LunarTime {

  /**
   * 天干下标，0-9
   */
  private final int ganIndex;

  /**
   * 地支下标，0-11
   */
  private final int zhiIndex;

  /**
   * 阴历
   */
  private final Lunar lunar;

  public LunarTime(int lunarYear, int lunarMonth, int lunarDay, int hour, int minute, int second) {
    this.lunar = Lunar.fromYmdHms(lunarYear, lunarMonth, lunarDay, hour, minute, second);
    this.zhiIndex = LunarUtil.getTimeZhiIndex(String.format("%02d:%02d", hour, minute));
    this.ganIndex = (lunar.getDayGanIndexExact() % 5 * 2 + zhiIndex) % 10;
  }

  public static LunarTime fromYmdHms(int lunarYear, int lunarMonth, int lunarDay, int hour, int minute, int second) {
    return new LunarTime(lunarYear, lunarMonth, lunarDay, hour, minute, second);
  }

  public int getGanIndex() {
    return ganIndex;
  }

  public int getZhiIndex() {
    return zhiIndex;
  }

  /**
   * 获取生肖
   *
   * @return 生肖，如虎
   */
  public String getShengXiao() {
    return LunarUtil.SHENGXIAO[zhiIndex + 1];
  }

  /**
   * 获取地支
   *
   * @return 地支
   */
  public String getZhi() {
    return LunarUtil.ZHI[zhiIndex + 1];
  }

  /**
   * 获取天干
   *
   * @return 天干
   */
  public String getGan() {
    return LunarUtil.GAN[ganIndex + 1];
  }

  /**
   * 获取干支（时柱）
   *
   * @return 干支（时柱）
   */
  public String getGanZhi() {
    return getGan() + getZhi();
  }

  /**
   * 获取喜神方位
   *
   * @return 喜神方位，如艮
   */
  public String getPositionXi() {
    return LunarUtil.POSITION_XI[ganIndex + 1];
  }

  /**
   * 获取喜神方位描述
   *
   * @return 喜神方位描述，如东北
   */
  public String getPositionXiDesc() {
    return LunarUtil.POSITION_DESC.get(getPositionXi());
  }

  /**
   * 获取阳贵神方位
   *
   * @return 阳贵神方位，如艮
   */
  public String getPositionYangGui() {
    return LunarUtil.POSITION_YANG_GUI[ganIndex + 1];
  }

  /**
   * 获取阳贵神方位描述
   *
   * @return 阳贵神方位描述，如东北
   */
  public String getPositionYangGuiDesc() {
    return LunarUtil.POSITION_DESC.get(getPositionYangGui());
  }

  /**
   * 获取阴贵神方位
   *
   * @return 阴贵神方位，如艮
   */
  public String getPositionYinGui() {
    return LunarUtil.POSITION_YIN_GUI[ganIndex + 1];
  }

  /**
   * 获取阴贵神方位描述
   *
   * @return 阴贵神方位描述，如东北
   */
  public String getPositionYinGuiDesc() {
    return LunarUtil.POSITION_DESC.get(getPositionYinGui());
  }

  /**
   * 获取福神方位（默认流派：2）
   *
   * @return 福神方位，如艮
   */
  public String getPositionFu() {
    return getPositionFu(2);
  }

  /**
   * 获取福神方位
   *
   * @param sect 流派，1或2
   * @return 福神方位，如艮
   */
  public String getPositionFu(int sect) {
    return (1 == sect ? LunarUtil.POSITION_FU : LunarUtil.POSITION_FU_2)[ganIndex + 1];
  }

  /**
   * 获取福神方位描述（默认流派：2）
   *
   * @return 福神方位描述，如东北
   */
  public String getPositionFuDesc() {
    return getPositionFuDesc(2);
  }

  /**
   * 获取福神方位描述
   *
   * @param sect 流派，1或2
   * @return 福神方位描述，如东北
   */
  public String getPositionFuDesc(int sect) {
    return LunarUtil.POSITION_DESC.get(getPositionFu(sect));
  }

  /**
   * 获取财神方位
   *
   * @return 财神方位，如艮
   */
  public String getPositionCai() {
    return LunarUtil.POSITION_CAI[ganIndex + 1];
  }

  /**
   * 获取财神方位描述
   *
   * @return 财神方位描述，如东北
   */
  public String getPositionCaiDesc() {
    return LunarUtil.POSITION_DESC.get(getPositionCai());
  }

  /**
   * 获取纳音
   *
   * @return 纳音，如剑锋金
   */
  public String getNaYin() {
    return LunarUtil.NAYIN.get(getGanZhi());
  }

  /**
   * 获取值时天神
   *
   * @return 值时天神
   */
  public String getTianShen() {
    String dayZhi = lunar.getDayZhiExact();
    int offset = LunarUtil.ZHI_TIAN_SHEN_OFFSET.get(dayZhi);
    return LunarUtil.TIAN_SHEN[(zhiIndex + offset) % 12 + 1];
  }

  /**
   * 获取值时天神类型：黄道/黑道
   *
   * @return 值时天神类型：黄道/黑道
   */
  public String getTianShenType() {
    return LunarUtil.TIAN_SHEN_TYPE.get(getTianShen());
  }

  /**
   * 获取值时天神吉凶
   *
   * @return 吉/凶
   */
  public String getTianShenLuck() {
    return LunarUtil.TIAN_SHEN_TYPE_LUCK.get(getTianShenType());
  }

  /**
   * 获取时冲
   *
   * @return 时冲，如申
   */
  public String getChong() {
    return LunarUtil.CHONG[zhiIndex];
  }

  /**
   * 获取时煞
   *
   * @return 时煞，如北
   */
  public String getSha() {
    return LunarUtil.SHA.get(getZhi());
  }

  /**
   * 获取时冲生肖
   *
   * @return 时冲生肖，如猴
   */
  public String getChongShengXiao() {
    String chong = getChong();
    for (int i = 0, j = LunarUtil.ZHI.length; i < j; i++) {
      if (LunarUtil.ZHI[i].equals(chong)) {
        return LunarUtil.SHENGXIAO[i];
      }
    }
    return "";
  }

  /**
   * 获取时冲描述
   *
   * @return 时冲描述，如(壬申)猴
   */
  public String getChongDesc() {
    return "(" + getChongGan() + getChong() + ")" + getChongShengXiao();
  }

  /**
   * 获取无情之克的时冲天干
   *
   * @return 无情之克的时冲天干，如甲
   */
  public String getChongGan() {
    return LunarUtil.CHONG_GAN[ganIndex];
  }

  /**
   * 获取有情之克的时冲天干
   *
   * @return 有情之克的时冲天干，如甲
   */
  public String getChongGanTie() {
    return LunarUtil.CHONG_GAN_TIE[ganIndex];
  }

  /**
   * 获取宜，如果没有，返回["无"]
   *
   * @return 宜
   */
  public List<String> getYi() {
    return LunarUtil.getTimeYi(lunar.getDayInGanZhiExact(), getGanZhi());
  }

  /**
   * 获取忌，如果没有，返回["无"]
   *
   * @return 忌
   */
  public List<String> getJi() {
    return LunarUtil.getTimeJi(lunar.getDayInGanZhiExact(), getGanZhi());
  }

  /**
   * 获取值时九星（时家紫白星歌诀：三元时白最为佳，冬至阳生顺莫差，孟日七宫仲一白，季日四绿发萌芽，每把时辰起甲子，本时星耀照光华，时星移入中宫去，顺飞八方逐细查。夏至阴生逆回首，孟归三碧季加六，仲在九宫时起甲，依然掌中逆轮跨。）
   *
   * @return 值时九星
   */
  public NineStar getNineStar() {
    //顺逆
    String solarYmd = lunar.getSolar().toYmd();
    Map<String, Solar> jieQi = lunar.getJieQiTable();
    boolean asc = solarYmd.compareTo(jieQi.get("冬至").toYmd()) >= 0 && solarYmd.compareTo(jieQi.get("夏至").toYmd()) < 0;
    int start = asc ? 7 : 3;
    String dayZhi = lunar.getDayZhi();
    if ("子午卯酉".contains(dayZhi)) {
      start = asc ? 1 : 9;
    } else if ("辰戌丑未".contains(dayZhi)) {
      start = asc ? 4 : 6;
    }
    int index = asc ? start + zhiIndex - 1 : start - zhiIndex - 1;
    if (index > 8) {
      index -= 9;
    }
    if (index < 0) {
      index += 9;
    }
    return new NineStar(index);
  }

  /**
   * 获取所在旬
   *
   * @return 旬
   */
  public String getXun() {
    return LunarUtil.getXun(getGanZhi());
  }

  /**
   * 获取值时空亡
   *
   * @return 空亡(旬空)
   */
  public String getXunKong() {
    return LunarUtil.getXunKong(getGanZhi());
  }

  /**
   * 获取当前时辰的最早时分
   *
   * @return 时分，如：21:00
   */
  public String getMinHm() {
    int hour = lunar.getHour();
    if (hour < 1) {
      return "00:00";
    } else if (hour > 22) {
      return "23:00";
    }
    return String.format("%02d:00", hour % 2 == 0 ? hour - 1 : hour);
  }

  /**
   * 获取当前时辰的最晚时分
   *
   * @return 时分，如：22:59
   */
  public String getMaxHm() {
    int hour = lunar.getHour();
    if (hour < 1) {
      return "00:59";
    } else if (hour > 22) {
      return "23:59";
    }
    return String.format("%02d:59", hour % 2 == 0 ? hour : hour + 1);
  }

  @Override
  public String toString() {
    return getGanZhi();
  }

}
