package templates

import scala.xml.Node

abstract class TradeTemplate(source: Node) extends RegiAmendTradeTemplate(source) {
  protected[this] def templateTradeBody: Node

  protected[this] def templateTrade: Node = {
    <fpml:trade>
      <fpml:tradeHeader>
        { /* Uses dictionary from PartyTemplate for identifier */ }
        <fpml:partyTradeIdentifier>
          <fpml:partyReference href={ parties("TradeRepository")._1 }/>
          { val tradeId = get((source \\ "trade" \ "tradeHeader" \ "partyTradeIdentifier" \ "tradeId")).mkString
            if (tradeId != "NONREF")
              <fpml:tradeId tradeIdScheme={ "REP" }>{ tradeId }</fpml:tradeId>
          }
          <fpml:tradeId tradeIdScheme={ "UTI" }>{ get((source \\ "trade" \ "tradeHeader" \ "partyTradeIdentifier").filter(_.child.filter(_.attributes.nonEmpty).head.attributes("href").text.mkString == "UTIGeneratingParty") \ "tradeId") }</fpml:tradeId>
        </fpml:partyTradeIdentifier>
        { for { s <- source \\ "trade" \ "tradeHeader" \ "partyTradeIdentifier"
                id = get(s \ "partyReference", "href").mkString
                if id != "Sender" && id != "UTIGeneratingParty"  && id != "TradeRepository"} yield {
            <fpml:partyTradeIdentifier>
              <fpml:partyReference href={ parties(id)._1 }/>
              <fpml:tradeId tradeIdScheme={ get(s \ "tradeId", "tradeIdScheme") }>{ get(s \ "tradeId") }</fpml:tradeId>
            </fpml:partyTradeIdentifier>
          }
        }
        <fpml:partyTradeInformation>
          { /* Uses dictionary from PartyTemplate for identifier */ }
          <fpml:partyReference href={ parties(get(source \\ "trade" \ "tradeHeader" \ "partyTradeInformation" \ "partyReference", "href").mkString)._1 }/>
          <fpml:relatedParty>
            { /* Uses dictionary from PartyTemplate for identifier */ }
            <fpml:partyReference href={ parties(get(source \\ "trade" \ "tradeHeader" \ "partyTradeInformation" \ "partyReference", "href").mkString)._1 } />
            <fpml:role>ClearingOrganization</fpml:role>
          </fpml:relatedParty>
          {/* value isn`t present in the source */}
          <fpml:category categoryScheme="http://www.fpml.ru/repository/trade-settlement-type">{ get(source \\ "trade" \ "nsdSpecificTradeFields" \ "clearSettlementType") }</fpml:category>
          <fpml:category categoryScheme="http://www.fpml.ru/repository/trade-settlement-method">{ get(source \\ "trade" \ "nsdSpecificTradeFields" \ "clearSettlementMethod") }</fpml:category>
          {/* value isn`t present in the source */}
          <fpml:executionDateTime>{ get(source \\ "trade" \ "tradeHeader" \ "tradeDate") + "T00:00:00" }</fpml:executionDateTime>
          <fpml:reportingRegime>
            <fpml:name>{ get(source \\ "trade" \ "tradeHeader" \ "partyTradeInformation" \ "reportingRegime" \ "name") }</fpml:name>
            {/* value isn`t present in the source. Rule from xls file */}
            <fpml:mandatorilyClearable>{ if (get(source \\ "trade" \ "nsdSpecificTradeFields" \ "cleared").mkString.contains("Y")) "true" else msgNotFound }</fpml:mandatorilyClearable>
          </fpml:reportingRegime>
        </fpml:partyTradeInformation>
        { /* Uses dictionary from PartyTemplate for identifier */
          for (p <- parties.filterKeys(_.startsWith("Party"))) yield
            <fpml:partyTradeInformation>
              <fpml:partyReference href={ p._2._1 } />
                { for { s <- source \\ "trade" \ "nsdSpecificTradeFields" \ "clientDetails"
                        if parties(get(s \ "servicingParty", "href").mkString)._1 == p._2._1
                        id = get(s \ "id").mkString
                        if id != msgNotFound } yield {
                    <fpml:relatedParty>
                      <fpml:partyReference href={ parties(id)._1 } />
                      <fpml:role>{ "Client" }</fpml:role>
                      <fpml:type>{ get(s \ "type") }</fpml:type>
                    </fpml:relatedParty>
                  }
                }
                <fpml:timestamps>
                  <fpml:timestamp>
                    <fpml:type>{ if (get(source \\ "trade" \ "nsdSpecificTradeFields" \ "clearedDate").mkString != msgNotFound) "InClearingPool" else msgNotFound}</fpml:type>
                    {/* value isn`t present in the source */}
                    <fpml:value>{
                      val d = get(source \\ "trade" \ "nsdSpecificTradeFields" \ "clearedDate")
                      if (d.mkString != msgNotFound) d + "T00:00:00" else msgNotFound
                      }</fpml:value>
                  </fpml:timestamp>
                  <fpml:timestamp>
                    <fpml:type>{ if (get(source \\ "trade" \ "nsdSpecificTradeFields" \ "startAgreementDate").mkString != msgNotFound) "InPortfolio" else msgNotFound}</fpml:type>
                    {/* value isn`t present in the source */}
                    <fpml:value>{
                      val d = get(source \\ "trade" \ "nsdSpecificTradeFields" \ "startAgreementDate")
                      if (d.mkString != msgNotFound) d + "T00:00:00" else msgNotFound
                      }</fpml:value>
                  </fpml:timestamp>
                  <fpml:timestamp>
                    <fpml:type>{ if (get(source \\ "trade" \ "nsdSpecificTradeFields" \ "endAgreementDate").mkString != msgNotFound) "OutPortfolio" else msgNotFound}</fpml:type>
                    {/* value isn`t present in the source */}
                    <fpml:value>{
                      val d = get(source \\ "trade" \ "nsdSpecificTradeFields" \ "endAgreementDate")
                      if (d.mkString != msgNotFound) d + "T00:00:00" else msgNotFound
                      }</fpml:value>
                  </fpml:timestamp>
                </fpml:timestamps>
                {/* value isn`t present in the source */}
                <fpml:collateralizationType>{
                  get(source \\ "trade" \ "collateral" \ "marginType").mkString match {
                    case "FC" => "Fully"
                    case "PC" => "Partially"
                    case "OC" => "OneWay"
                    case "U" => "Uncollateralized"
                    case _  => msgNotFound
                  }
                  }</fpml:collateralizationType>
                {/* value isn`t present in the source */}
                <fpml:collateralPortfolio>{ get(source \\ "trade" \ "collateral" \ "collateralForm") }</fpml:collateralPortfolio>
            </fpml:partyTradeInformation>
        }
      </fpml:tradeHeader>
      { templateTradeBody }
      <fpml:documentation>
        <fpml:masterAgreement>
          <fpml:masterAgreementId>{
            val id = get(source \\ "trade" \ "tradeHeader" \ "partyTradeIdentifier" \ "linkId").mkString
            if (id != msgNotFound) id else "NONREF"
          }</fpml:masterAgreementId>
        </fpml:masterAgreement>
      </fpml:documentation>
    </fpml:trade>
  }
}
