use crate::msgs::enums::{ContentType, HandshakeType, ProtocolVersion};
use crate::msgs::enums::{AlertDescription, SignatureScheme, NamedGroup};
use crate::msgs::enums::{Compression, PSKKeyExchangeMode};
use crate::msgs::enums::KeyUpdateRequest;
use crate::msgs::message::{Message, MessagePayload};
use crate::msgs::handshake::HandshakePayload;
use crate::msgs::handshake::HandshakeMessagePayload;
use crate::msgs::handshake::NewSessionTicketPayloadTLS13;
use crate::msgs::handshake::CertificateEntry;
use crate::msgs::handshake::CertificateExtension;
use crate::msgs::handshake::CertificateStatus;
use crate::msgs::handshake::CertificatePayloadTLS13;
use crate::msgs::handshake::CertificateRequestPayloadTLS13;
use crate::msgs::handshake::CertReqExtension;
use crate::msgs::handshake::ClientHelloPayload;
use crate::msgs::handshake::HelloRetryRequest;
use crate::msgs::handshake::HelloRetryExtension;
use crate::msgs::handshake::ServerHelloPayload;
use crate::msgs::handshake::KeyShareEntry;
use crate::msgs::handshake::SessionID;
use crate::msgs::handshake::ServerExtension;
use crate::msgs::handshake::Random;
use crate::msgs::handshake::DigitallySignedStruct;
use crate::msgs::ccs::ChangeCipherSpecPayload;
use crate::msgs::base::{Payload, PayloadU8};
use crate::msgs::codec::Codec;
use crate::msgs::persist;
use crate::server::ServerSessionImpl;
use crate::key_schedule::{
    KeyScheduleNonSecret,
    KeyScheduleEarly,
    KeyScheduleHandshake,
    KeyScheduleTrafficWithClientFinishedPending,
    KeyScheduleTraffic
};
use crate::cipher;
use crate::verify;
use crate::rand;
use crate::sign;
use crate::suites;
#[cfg(feature = "logging")]
use crate::log::{warn, trace, debug};
use crate::error::TLSError;
use crate::handshake::{check_handshake_message, check_message};
#[cfg(feature = "quic")]
use crate::{
    quic,
    msgs::handshake::NewSessionTicketExtension,
    session::Protocol
};

use crate::server::common::{HandshakeDetails, ClientCertDetails};
use crate::server::hs;

use ring::constant_time;

pub struct CompleteClientHelloHandling {
    pub handshake: HandshakeDetails,
    pub done_retry: bool,
    pub send_cert_status: bool,
    pub send_sct: bool,
    pub send_ticket: bool,
}

impl CompleteClientHelloHandling {
    fn check_binder(&self,
                    sess: &mut ServerSessionImpl,
                    client_hello: &Message,
                    psk: &[u8],
                    binder: &[u8])
                    -> bool {
        let binder_plaintext = match client_hello.payload {
            MessagePayload::Handshake(ref hmp) => hmp.get_encoding_for_binder_signing(),
            _ => unreachable!(),
        };

        let suite = sess.common.get_suite_assert();
        let suite_hash = suite.get_hash();
        let handshake_hash = self.handshake.transcript.get_hash_given(suite_hash, &binder_plaintext);

        let key_schedule = KeyScheduleEarly::new(suite.hkdf_algorithm, &psk);
        let real_binder = key_schedule.resumption_psk_binder_key_and_sign_verify_data(&handshake_hash);

        constant_time::verify_slices_are_equal(&real_binder, binder).is_ok()
    }

    fn into_expect_retried_client_hello(self) -> hs::NextState {
        Box::new(hs::ExpectClientHello {
            handshake: self.handshake,
            done_retry: true,
            send_cert_status: self.send_cert_status,
            send_sct: self.send_sct,
            send_ticket: self.send_ticket,
        })
    }

    fn into_expect_certificate(self, key_schedule: KeyScheduleTrafficWithClientFinishedPending) -> hs::NextState {
        Box::new(ExpectCertificate {
            handshake: self.handshake,
            key_schedule,
            send_ticket: self.send_ticket,
        })
    }

    fn into_expect_finished(self, key_schedule: KeyScheduleTrafficWithClientFinishedPending) -> hs::NextState {
        Box::new(ExpectFinished {
            handshake: self.handshake,
            key_schedule,
            send_ticket: self.send_ticket,
        })
    }

    fn emit_server_hello(&mut self,
                         sess: &mut ServerSessionImpl,
                         session_id: &SessionID,
                         share: &KeyShareEntry,
                         chosen_psk_idx: Option<usize>,
                         resuming_psk: Option<&[u8]>)
                           -> Result<KeyScheduleHandshake, TLSError> {
        let mut extensions = Vec::new();

        // Do key exchange
        let kxr = suites::KeyExchange::start_ecdhe(share.group)
            .and_then(|kx| kx.complete(&share.payload.0))
            .ok_or_else(|| TLSError::PeerMisbehavedError("key exchange failed".to_string()))?;

        let kse = KeyShareEntry::new(share.group, kxr.pubkey.as_ref());
        extensions.push(ServerExtension::KeyShare(kse));
        extensions.push(ServerExtension::SupportedVersions(ProtocolVersion::TLSv1_3));

        if let Some(psk_idx) = chosen_psk_idx {
            extensions.push(ServerExtension::PresharedKey(psk_idx as u16));
        }

        let sh = Message {
            typ: ContentType::Handshake,
            version: ProtocolVersion::TLSv1_2,
            payload: MessagePayload::Handshake(HandshakeMessagePayload {
                typ: HandshakeType::ServerHello,
                payload: HandshakePayload::ServerHello(ServerHelloPayload {
                    legacy_version: ProtocolVersion::TLSv1_2,
                    random: Random::from_slice(&self.handshake.randoms.server),
                    session_id: *session_id,
                    cipher_suite: sess.common.get_suite_assert().suite,
                    compression_method: Compression::Null,
                    extensions,
                }),
            }),
        };

        hs::check_aligned_handshake(sess)?;

        #[cfg(feature = "quic")]
        let client_hello_hash = self.handshake.transcript
            .get_hash_given(sess.common.get_suite_assert().get_hash(), &[]);

        trace!("sending server hello {:?}", sh);
        self.handshake.transcript.add_message(&sh);
        sess.common.send_msg(sh, false);

        // Start key schedule
        let suite = sess.common.get_suite_assert();
        let mut key_schedule = if let Some(psk) = resuming_psk {
            let early_key_schedule = KeyScheduleEarly::new(suite.hkdf_algorithm, psk);

            #[cfg(feature = "quic")] {
                if sess.common.protocol == Protocol::Quic {
                    let client_early_traffic_secret = early_key_schedule
                        .client_early_traffic_secret(&client_hello_hash,
                                                     &*sess.config.key_log,
                                                     &self.handshake.randoms.client);
                    // If 0-RTT should be rejected, this will be clobbered by ExtensionProcessing
                    // before the application can see.
                    sess.common.quic.early_secret = Some(client_early_traffic_secret);
                }
            }

            early_key_schedule
                .into_handshake(&kxr.shared_secret)
        } else {
            KeyScheduleNonSecret::new(suite.hkdf_algorithm)
                .into_handshake(&kxr.shared_secret)
        };

        let handshake_hash = self.handshake.transcript.get_current_hash();
        let write_key = key_schedule
            .server_handshake_traffic_secret(&handshake_hash,
                                             &*sess.config.key_log,
                                             &self.handshake.randoms.client);
        sess.common
            .record_layer
            .set_message_encrypter(cipher::new_tls13_write(suite, &write_key));

        let read_key = key_schedule
            .client_handshake_traffic_secret(&handshake_hash,
                                             &*sess.config.key_log,
                                             &self.handshake.randoms.client);
        sess.common
            .record_layer
            .set_message_decrypter(cipher::new_tls13_read(suite, &read_key));

        #[cfg(feature = "quic")] {
            sess.common.quic.hs_secrets = Some(quic::Secrets {
                client: read_key,
                server: write_key,
            });
        }

        Ok(key_schedule)
    }

    fn emit_fake_ccs(&mut self,
                     sess: &mut ServerSessionImpl) {
        #[cfg(feature = "quic")] {
            if let Protocol::Quic = sess.common.protocol { return; }
        }
        let m = Message {
            typ: ContentType::ChangeCipherSpec,
            version: ProtocolVersion::TLSv1_2,
            payload: MessagePayload::ChangeCipherSpec(ChangeCipherSpecPayload {})
        };
        sess.common.send_msg(m, false);
    }

    fn emit_hello_retry_request(&mut self,
                                sess: &mut ServerSessionImpl,
                                group: NamedGroup) {
        let mut req = HelloRetryRequest {
            legacy_version: ProtocolVersion::TLSv1_2,
            session_id: SessionID::empty(),
            cipher_suite: sess.common.get_suite_assert().suite,
            extensions: Vec::new(),
        };

        req.extensions.push(HelloRetryExtension::KeyShare(group));
        req.extensions.push(HelloRetryExtension::SupportedVersions(ProtocolVersion::TLSv1_3));

        let m = Message {
            typ: ContentType::Handshake,
            version: ProtocolVersion::TLSv1_2,
            payload: MessagePayload::Handshake(HandshakeMessagePayload {
                typ: HandshakeType::HelloRetryRequest,
                payload: HandshakePayload::HelloRetryRequest(req),
            }),
        };

        trace!("Requesting retry {:?}", m);
        self.handshake.transcript.rollup_for_hrr();
        self.handshake.transcript.add_message(&m);
        sess.common.send_msg(m, false);
    }

    fn emit_encrypted_extensions(&mut self,
                                 sess: &mut ServerSessionImpl,
                                 server_key: &mut sign::CertifiedKey,
                                 hello: &ClientHelloPayload,
                                 resumedata: Option<&persist::ServerSessionValue>)
                                 -> Result<(), TLSError> {
        let mut ep = hs::ExtensionProcessing::new();
        ep.process_common(sess, Some(server_key), hello, resumedata, &self.handshake)?;

        self.send_cert_status = ep.send_cert_status;
        self.send_sct = ep.send_sct;

        let ee = Message {
            typ: ContentType::Handshake,
            version: ProtocolVersion::TLSv1_3,
            payload: MessagePayload::Handshake(HandshakeMessagePayload {
                typ: HandshakeType::EncryptedExtensions,
                payload: HandshakePayload::EncryptedExtensions(ep.exts),
            }),
        };

        trace!("sending encrypted extensions {:?}", ee);
        self.handshake.transcript.add_message(&ee);
        sess.common.send_msg(ee, true);
        Ok(())
    }

    fn emit_certificate_req_tls13(&mut self, sess: &mut ServerSessionImpl) -> Result<bool, TLSError> {
        if !sess.config.verifier.offer_client_auth() {
            return Ok(false);
        }

        let mut cr = CertificateRequestPayloadTLS13 {
            context: PayloadU8::empty(),
            extensions: Vec::new(),
        };

        let schemes = verify::supported_verify_schemes();
        cr.extensions.push(CertReqExtension::SignatureAlgorithms(schemes.to_vec()));

        let names = sess.config.verifier.client_auth_root_subjects(sess.get_sni())
            .ok_or_else(|| {
                debug!("could not determine root subjects based on SNI");
                sess.common.send_fatal_alert(AlertDescription::AccessDenied);
                TLSError::General("client rejected by client_auth_root_subjects".into())
            })?;

        if !names.is_empty() {
            cr.extensions.push(CertReqExtension::AuthorityNames(names));
        }

        let m = Message {
            typ: ContentType::Handshake,
            version: ProtocolVersion::TLSv1_3,
            payload: MessagePayload::Handshake(HandshakeMessagePayload {
                typ: HandshakeType::CertificateRequest,
                payload: HandshakePayload::CertificateRequestTLS13(cr),
            }),
        };

        trace!("Sending CertificateRequest {:?}", m);
        self.handshake.transcript.add_message(&m);
        sess.common.send_msg(m, true);
        Ok(true)
    }

    fn emit_certificate_tls13(&mut self,
                              sess: &mut ServerSessionImpl,
                              server_key: &mut sign::CertifiedKey) {
        let mut cert_entries = vec![];
        for cert in server_key.take_cert() {
            let entry = CertificateEntry {
                cert,
                exts: Vec::new(),
            };

            cert_entries.push(entry);
        }

        if let Some(end_entity_cert) = cert_entries.first_mut() {
            // Apply OCSP response to first certificate (we don't support OCSP
            // except for leaf certs).
            if self.send_cert_status {
                if let Some(ocsp) = server_key.take_ocsp() {
                    let cst = CertificateStatus::new(ocsp);
                    end_entity_cert.exts.push(CertificateExtension::CertificateStatus(cst));
                }
            }

            // Likewise, SCT
            if self.send_sct {
                if let Some(sct_list) = server_key.take_sct_list() {
                    end_entity_cert.exts.push(CertificateExtension::make_sct(sct_list));
                }
            }
        }

        let cert_body = CertificatePayloadTLS13::new(cert_entries);
        let c = Message {
            typ: ContentType::Handshake,
            version: ProtocolVersion::TLSv1_3,
            payload: MessagePayload::Handshake(HandshakeMessagePayload {
                typ: HandshakeType::Certificate,
                payload: HandshakePayload::CertificateTLS13(cert_body),
            }),
        };

        trace!("sending certificate {:?}", c);
        self.handshake.transcript.add_message(&c);
        sess.common.send_msg(c, true);
    }

    fn emit_certificate_verify_tls13(&mut self,
                                     sess: &mut ServerSessionImpl,
                                     server_key: &mut sign::CertifiedKey,
                                     schemes: &[SignatureScheme])
                                     -> Result<(), TLSError> {
        let mut message = Vec::new();
        message.resize(64, 0x20u8);
        message.extend_from_slice(b"TLS 1.3, server CertificateVerify\x00");
        message.extend_from_slice(&self.handshake.transcript.get_current_hash());

        let signing_key = &server_key.key;
        let signer = signing_key.choose_scheme(schemes)
            .ok_or_else(|| hs::incompatible(sess, "no overlapping sigschemes"))?;

        let scheme = signer.get_scheme();
        let sig = signer.sign(&message)?;

        let cv = DigitallySignedStruct::new(scheme, sig);

        let m = Message {
            typ: ContentType::Handshake,
            version: ProtocolVersion::TLSv1_3,
            payload: MessagePayload::Handshake(HandshakeMessagePayload {
                typ: HandshakeType::CertificateVerify,
                payload: HandshakePayload::CertificateVerify(cv),
            }),
        };

        trace!("sending certificate-verify {:?}", m);
        self.handshake.transcript.add_message(&m);
        sess.common.send_msg(m, true);
        Ok(())
    }

    fn emit_finished_tls13(&mut self, sess: &mut ServerSessionImpl,
                           key_schedule: KeyScheduleHandshake) -> KeyScheduleTrafficWithClientFinishedPending {
        let handshake_hash = self.handshake.transcript.get_current_hash();
        let verify_data = key_schedule.sign_server_finish(&handshake_hash);
        let verify_data_payload = Payload::new(verify_data);

        let m = Message {
            typ: ContentType::Handshake,
            version: ProtocolVersion::TLSv1_3,
            payload: MessagePayload::Handshake(HandshakeMessagePayload {
                typ: HandshakeType::Finished,
                payload: HandshakePayload::Finished(verify_data_payload),
            }),
        };

        trace!("sending finished {:?}", m);
        self.handshake.transcript.add_message(&m);
        self.handshake.hash_at_server_fin = self.handshake.transcript.get_current_hash();
        sess.common.send_msg(m, true);

        // Now move to application data keys.  Read key change is deferred until
        // the Finish message is received & validated.
        let mut key_schedule_traffic = key_schedule.into_traffic_with_client_finished_pending();
        let suite = sess.common.get_suite_assert();
        let write_key = key_schedule_traffic
            .server_application_traffic_secret(&self.handshake.hash_at_server_fin,
                                               &*sess.config.key_log,
                                               &self.handshake.randoms.client);
        sess.common
            .record_layer
            .set_message_encrypter(cipher::new_tls13_write(suite, &write_key));

        key_schedule_traffic
            .exporter_master_secret(&self.handshake.hash_at_server_fin,
                                    &*sess.config.key_log,
                                    &self.handshake.randoms.client);

        let _read_key = key_schedule_traffic
            .client_application_traffic_secret(&self.handshake.hash_at_server_fin,
                                               &*sess.config.key_log,
                                               &self.handshake.randoms.client);

        #[cfg(feature = "quic")] {
            sess.common.quic.traffic_secrets = Some(quic::Secrets {
                client: _read_key,
                server: write_key,
            });
        }

        key_schedule_traffic
    }

    fn attempt_tls13_ticket_decryption(&mut self,
                                       sess: &mut ServerSessionImpl,
                                       ticket: &[u8]) -> Option<persist::ServerSessionValue> {
        if sess.config.ticketer.enabled() {
            sess.config
                .ticketer
                .decrypt(ticket)
                .and_then(|plain| persist::ServerSessionValue::read_bytes(&plain))
        } else {
            sess.config
                .session_storage
                .take(ticket)
                .and_then(|plain| persist::ServerSessionValue::read_bytes(&plain))
        }
    }

    pub fn handle_client_hello(mut self,
                               sess: &mut ServerSessionImpl,
                               sni: Option<webpki::DNSName>,
                               mut server_key: sign::CertifiedKey,
                               chm: &Message) -> hs::NextStateOrError {
        let client_hello = extract_handshake!(chm, HandshakePayload::ClientHello).unwrap();

        if client_hello.compression_methods.len() != 1 {
            return Err(hs::illegal_param(sess, "client offered wrong compressions"));
        }

        let groups_ext = client_hello.get_namedgroups_extension()
            .ok_or_else(|| hs::incompatible(sess, "client didn't describe groups"))?;

        let mut sigschemes_ext = client_hello.get_sigalgs_extension()
            .ok_or_else(|| hs::incompatible(sess, "client didn't describe sigschemes"))?
            .clone();

        let tls13_schemes = sign::supported_sign_tls13();
        sigschemes_ext.retain(|scheme| tls13_schemes.contains(scheme));

        let shares_ext = client_hello.get_keyshare_extension()
            .ok_or_else(|| hs::incompatible(sess, "client didn't send keyshares"))?;

        if client_hello.has_keyshare_extension_with_duplicates() {
            return Err(hs::illegal_param(sess, "client sent duplicate keyshares"));
        }

        let share_groups: Vec<NamedGroup> = shares_ext.iter()
            .map(|share| share.group)
            .collect();

        let supported_groups = suites::KeyExchange::supported_groups();
        let chosen_group = supported_groups
            .iter()
            .filter(|group| share_groups.contains(group))
            .nth(0)
            .cloned();

        if chosen_group.is_none() {
            // We don't have a suitable key share.  Choose a suitable group and
            // send a HelloRetryRequest.
            let retry_group_maybe = supported_groups
                .iter()
                .filter(|group| groups_ext.contains(group))
                .nth(0)
                .cloned();
            self.handshake.transcript.add_message(chm);

            if let Some(group) = retry_group_maybe {
                if self.done_retry {
                    return Err(hs::illegal_param(sess, "did not follow retry request"));
                }

                self.emit_hello_retry_request(sess, group);
                self.emit_fake_ccs(sess);
                return Ok(self.into_expect_retried_client_hello());
            }

            return Err(hs::incompatible(sess, "no kx group overlap with client"));
        }

        hs::save_sni(sess, sni);

        let chosen_group = chosen_group.unwrap();
        let chosen_share = shares_ext.iter()
            .find(|share| share.group == chosen_group)
            .unwrap();

        let mut chosen_psk_index = None;
        let mut resumedata = None;
        if let Some(psk_offer) = client_hello.get_psk() {
            if !client_hello.check_psk_ext_is_last() {
                return Err(hs::illegal_param(sess, "psk extension in wrong position"));
            }

            if psk_offer.binders.is_empty() {
                return Err(hs::decode_error(sess, "psk extension missing binder"));
            }

            if psk_offer.binders.len() != psk_offer.identities.len() {
                return Err(hs::illegal_param(sess, "psk extension mismatched ids/binders"));
            }

            for (i, psk_id) in psk_offer.identities.iter().enumerate() {
                let maybe_resume = self.attempt_tls13_ticket_decryption(sess, &psk_id.identity.0);

                if !hs::can_resume(sess, &self.handshake, &maybe_resume) {
                    continue;
                }

                let resume = maybe_resume.unwrap();

                if !self.check_binder(sess, chm, &resume.master_secret.0, &psk_offer.binders[i].0) {
                    sess.common.send_fatal_alert(AlertDescription::DecryptError);
                    return Err(TLSError::PeerMisbehavedError("client sent wrong binder".to_string()));
                }

                chosen_psk_index = Some(i);
                resumedata = Some(resume);
                break;
            }
        }

        if !client_hello.psk_mode_offered(PSKKeyExchangeMode::PSK_DHE_KE) {
            warn!("Resumption ignored, DHE_KE not offered");
            self.send_ticket = false;
            chosen_psk_index = None;
            resumedata = None;
        } else {
            self.send_ticket = true;
        }

        if let Some(ref resume) = resumedata {
            sess.received_resumption_data = Some(resume.application_data.0.clone());
        }

        let full_handshake = resumedata.is_none();
        self.handshake.transcript.add_message(chm);
        let key_schedule = self.emit_server_hello(sess, &client_hello.session_id,
                                                  chosen_share, chosen_psk_index,
                                                  resumedata.as_ref().map(|x| &x.master_secret.0[..]))?;
        if !self.done_retry {
            self.emit_fake_ccs(sess);
        }
        self.emit_encrypted_extensions(sess, &mut server_key, client_hello, resumedata.as_ref())?;

        let doing_client_auth = if full_handshake {
            let client_auth = self.emit_certificate_req_tls13(sess)?;
            self.emit_certificate_tls13(sess, &mut server_key);
            self.emit_certificate_verify_tls13(sess, &mut server_key, &sigschemes_ext)?;
            client_auth
        } else {
            false
        };

        hs::check_aligned_handshake(sess)?;
        let key_schedule_traffic = self.emit_finished_tls13(sess, key_schedule);

        if doing_client_auth {
            Ok(self.into_expect_certificate(key_schedule_traffic))
        } else {
            Ok(self.into_expect_finished(key_schedule_traffic))
        }
    }
}

pub struct ExpectCertificate {
    pub handshake: HandshakeDetails,
    pub key_schedule: KeyScheduleTrafficWithClientFinishedPending,
    pub send_ticket: bool,
}

impl ExpectCertificate {
    fn into_expect_finished(self) -> hs::NextState {
        Box::new(ExpectFinished {
            key_schedule: self.key_schedule,
            handshake: self.handshake,
            send_ticket: self.send_ticket,
        })
    }

    fn into_expect_certificate_verify(self,
                                      cert: ClientCertDetails) -> hs::NextState {
        Box::new(ExpectCertificateVerify {
            handshake: self.handshake,
            key_schedule: self.key_schedule,
            client_cert: cert,
            send_ticket: self.send_ticket,
        })
    }
}

impl hs::State for ExpectCertificate {
    fn check_message(&self, m: &Message) -> hs::CheckResult {
        check_handshake_message(m, &[HandshakeType::Certificate])
    }

    fn handle(mut self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> hs::NextStateOrError {
        let certp = extract_handshake!(m, HandshakePayload::CertificateTLS13).unwrap();
        self.handshake.transcript.add_message(&m);

        // We don't send any CertificateRequest extensions, so any extensions
        // here are illegal.
        if certp.any_entry_has_extension() {
            return Err(TLSError::PeerMisbehavedError("client sent unsolicited cert extension"
                                                     .to_string()));
        }

        let cert_chain = certp.convert();

        let mandatory = sess.config.verifier.client_auth_mandatory(sess.get_sni())
            .ok_or_else(|| {
                debug!("could not determine if client auth is mandatory based on SNI");
                sess.common.send_fatal_alert(AlertDescription::AccessDenied);
                TLSError::General("client rejected by client_auth_mandatory".into())
            })?;

        if cert_chain.is_empty() {
            if !mandatory {
                debug!("client auth requested but no certificate supplied");
                self.handshake.transcript.abandon_client_auth();
                return Ok(self.into_expect_finished());
            }

            sess.common.send_fatal_alert(AlertDescription::CertificateRequired);
            return Err(TLSError::NoCertificatesPresented);
        }

        sess.config.get_verifier().verify_client_cert(&cert_chain, sess.get_sni())
            .or_else(|err| {
                     hs::incompatible(sess, "certificate invalid");
                     Err(err)
                     })?;

        let cert = ClientCertDetails::new(cert_chain);
        Ok(self.into_expect_certificate_verify(cert))
    }
}

pub struct ExpectCertificateVerify {
    handshake: HandshakeDetails,
    key_schedule: KeyScheduleTrafficWithClientFinishedPending,
    client_cert: ClientCertDetails,
    send_ticket: bool,
}

impl ExpectCertificateVerify {
    fn into_expect_finished(self) -> hs::NextState {
        Box::new(ExpectFinished {
            key_schedule: self.key_schedule,
            handshake: self.handshake,
            send_ticket: self.send_ticket,
        })
    }
}

impl hs::State for ExpectCertificateVerify {
    fn check_message(&self, m: &Message) -> hs::CheckResult {
        check_handshake_message(m, &[HandshakeType::CertificateVerify])
    }

    fn handle(mut self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> hs::NextStateOrError {
        let rc = {
            let sig = extract_handshake!(m, HandshakePayload::CertificateVerify).unwrap();
            let handshake_hash = self.handshake.transcript.get_current_hash();
            self.handshake.transcript.abandon_client_auth();
            let certs = &self.client_cert.cert_chain;

            verify::verify_tls13(&certs[0],
                                 sig,
                                 &handshake_hash,
                                 b"TLS 1.3, client CertificateVerify\x00")
        };

        if let Err(e) = rc {
            sess.common.send_fatal_alert(AlertDescription::AccessDenied);
            return Err(e);
        }

        trace!("client CertificateVerify OK");
        sess.client_cert_chain = Some(self.client_cert.take_chain());

        self.handshake.transcript.add_message(&m);
        Ok(self.into_expect_finished())
    }
}

// --- Process client's Finished ---
fn get_server_session_value(handshake: &mut HandshakeDetails,
                            key_schedule: &KeyScheduleTraffic,
                            sess: &ServerSessionImpl,
                            nonce: &[u8]) -> persist::ServerSessionValue {
    let scs = sess.common.get_suite_assert();
    let version = ProtocolVersion::TLSv1_3;

    let handshake_hash = handshake
        .transcript
        .get_current_hash();
    let secret = key_schedule
        .resumption_master_secret_and_derive_ticket_psk(&handshake_hash, nonce);

    persist::ServerSessionValue::new(
        sess.get_sni(), version,
        scs.suite, secret,
        &sess.client_cert_chain,
        sess.alpn_protocol.clone(),
        sess.resumption_data.clone(),
    )
}

pub struct ExpectFinished {
    pub handshake: HandshakeDetails,
    pub key_schedule: KeyScheduleTrafficWithClientFinishedPending,
    pub send_ticket: bool,
}

impl ExpectFinished {
    fn into_expect_traffic(fin: verify::FinishedMessageVerified, ks: KeyScheduleTraffic) -> hs::NextState {
        Box::new(ExpectTraffic {
            key_schedule: ks,
            want_write_key_update: false,
            _fin_verified: fin,
        })
    }

    fn emit_stateless_ticket(handshake: &mut HandshakeDetails,
                             sess: &mut ServerSessionImpl,
                             key_schedule: &KeyScheduleTraffic) {
        let nonce = rand::random_vec(32);
        let plain = get_server_session_value(handshake,
                                             key_schedule,
                                             sess, &nonce)
            .get_encoding();
        let maybe_ticket = sess.config
            .ticketer
            .encrypt(&plain);
        let ticket_lifetime = sess.config.ticketer.get_lifetime();

        if maybe_ticket.is_none() {
            return;
        }

        let ticket = maybe_ticket.unwrap();
        let age_add = rand::random_u32(); // nb, we don't do 0-RTT data, so whatever
        #[allow(unused_mut)]
        let mut payload = NewSessionTicketPayloadTLS13::new(ticket_lifetime, age_add, nonce, ticket);
        #[cfg(feature = "quic")] {
            if sess.config.max_early_data_size > 0 && sess.common.protocol == Protocol::Quic {
                payload.exts.push(NewSessionTicketExtension::EarlyData(sess.config.max_early_data_size));
            }
        }
        let m = Message {
            typ: ContentType::Handshake,
            version: ProtocolVersion::TLSv1_3,
            payload: MessagePayload::Handshake(HandshakeMessagePayload {
                typ: HandshakeType::NewSessionTicket,
                payload: HandshakePayload::NewSessionTicketTLS13(payload),
            }),
        };

        trace!("sending new ticket {:?}", m);
        handshake.transcript.add_message(&m);
        sess.common.send_msg(m, true);
    }

    fn emit_stateful_ticket(handshake: &mut HandshakeDetails,
                            sess: &mut ServerSessionImpl,
                            key_schedule: &KeyScheduleTraffic) {
        let nonce = rand::random_vec(32);
        let id = rand::random_vec(32);
        let plain = get_server_session_value(handshake,
                                             key_schedule,
                                             sess, &nonce)
            .get_encoding();

        if sess.config.session_storage.put(id.clone(), plain) {
            let stateful_lifetime = 24 * 60 * 60; // this is a bit of a punt
            let age_add = rand::random_u32();
            #[allow(unused_mut)]
            let mut payload = NewSessionTicketPayloadTLS13::new(stateful_lifetime, age_add, nonce, id);
            #[cfg(feature = "quic")] {
                if sess.config.max_early_data_size > 0 && sess.common.protocol == Protocol::Quic {
                    payload.exts.push(NewSessionTicketExtension::EarlyData(sess.config.max_early_data_size));
                }
            }
            let m = Message {
                typ: ContentType::Handshake,
                version: ProtocolVersion::TLSv1_3,
                payload: MessagePayload::Handshake(HandshakeMessagePayload {
                    typ: HandshakeType::NewSessionTicket,
                    payload: HandshakePayload::NewSessionTicketTLS13(payload),
                }),
            };

            trace!("sending new stateful ticket {:?}", m);
            handshake.transcript.add_message(&m);
            sess.common.send_msg(m, true);
        } else {
            trace!("resumption not available; not issuing ticket");
        }
    }
}

impl hs::State for ExpectFinished {
    fn check_message(&self, m: &Message) -> hs::CheckResult {
        check_handshake_message(m, &[HandshakeType::Finished])
    }

    fn handle(mut self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> hs::NextStateOrError {
        let finished = extract_handshake!(m, HandshakePayload::Finished).unwrap();

        let handshake_hash = self.handshake.transcript.get_current_hash();
        let expect_verify_data = self.key_schedule.sign_client_finish(&handshake_hash);

        let fin = constant_time::verify_slices_are_equal(&expect_verify_data, &finished.0)
            .map_err(|_| {
                     sess.common.send_fatal_alert(AlertDescription::DecryptError);
                     warn!("Finished wrong");
                     TLSError::DecryptError
                     })
            .map(|_| verify::FinishedMessageVerified::assertion())?;

        // nb. future derivations include Client Finished, but not the
        // main application data keying.
        self.handshake.transcript.add_message(&m);

        hs::check_aligned_handshake(sess)?;

        let suite = sess.common.get_suite_assert();

        // Install keying to read future messages.
        let read_key = self.key_schedule
            .client_application_traffic_secret(&self.handshake.hash_at_server_fin,
                                               &*sess.config.key_log,
                                               &self.handshake.randoms.client);
        sess.common
            .record_layer
            .set_message_decrypter(cipher::new_tls13_read(suite, &read_key));

        let key_schedule_traffic = self.key_schedule.into_traffic();

        if self.send_ticket {
            if sess.config.ticketer.enabled() {
                Self::emit_stateless_ticket(&mut self.handshake, sess, &key_schedule_traffic);
            } else {
                Self::emit_stateful_ticket(&mut self.handshake, sess, &key_schedule_traffic);
            }
        }

        sess.common.start_traffic();

        #[cfg(feature = "quic")] {
            if sess.common.protocol == Protocol::Quic {
                return Ok(Box::new(ExpectQUICTraffic { _fin_verified: fin }));
            }
        }

        Ok(Self::into_expect_traffic(fin, key_schedule_traffic))
    }
}

// --- Process traffic ---
pub struct ExpectTraffic {
    key_schedule: KeyScheduleTraffic,
    want_write_key_update: bool,
    _fin_verified: verify::FinishedMessageVerified,
}

impl ExpectTraffic {
    fn handle_traffic(&self, sess: &mut ServerSessionImpl, mut m: Message) -> Result<(), TLSError> {
        sess.common.take_received_plaintext(m.take_opaque_payload().unwrap());
        Ok(())
    }

    fn handle_key_update(&mut self, sess: &mut ServerSessionImpl, m: Message) -> Result<(), TLSError> {
        let kur = extract_handshake!(m, HandshakePayload::KeyUpdate).unwrap();

        #[cfg(feature = "quic")]
        {
            if let Protocol::Quic = sess.common.protocol {
                sess.common.send_fatal_alert(AlertDescription::UnexpectedMessage);
                let msg = "KeyUpdate received in QUIC connection".to_string();
                warn!("{}", msg);
                return Err(TLSError::PeerMisbehavedError(msg));
            }
        }

        hs::check_aligned_handshake(sess)?;

        match kur {
            KeyUpdateRequest::UpdateNotRequested => {}
            KeyUpdateRequest::UpdateRequested => {
                self.want_write_key_update = true;
            }
            _ => {
                sess.common.send_fatal_alert(AlertDescription::IllegalParameter);
                return Err(TLSError::CorruptMessagePayload(ContentType::Handshake));
            }
        }

        // Update our read-side keys.
        let new_read_key = self.key_schedule.next_client_application_traffic_secret();
        let suite = sess.common.get_suite_assert();
        sess.common.record_layer.set_message_decrypter(cipher::new_tls13_read(suite, &new_read_key));

        Ok(())
    }
}

impl hs::State for ExpectTraffic {
    fn check_message(&self, m: &Message) -> hs::CheckResult {
        check_message(m,
                      &[ContentType::ApplicationData, ContentType::Handshake],
                      &[HandshakeType::KeyUpdate])
    }

    fn handle(mut self: Box<Self>, sess: &mut ServerSessionImpl, m: Message) -> hs::NextStateOrError {
        if m.is_content_type(ContentType::ApplicationData) {
            self.handle_traffic(sess, m)?;
        } else if m.is_handshake_type(HandshakeType::KeyUpdate) {
            self.handle_key_update(sess, m)?;
        }

        Ok(self)
    }

    fn export_keying_material(&self,
                              output: &mut [u8],
                              label: &[u8],
                              context: Option<&[u8]>) -> Result<(), TLSError> {
        self.key_schedule.export_keying_material(output, label, context)
    }

    fn perhaps_write_key_update(&mut self, sess: &mut ServerSessionImpl) {
        if self.want_write_key_update {
            self.want_write_key_update = false;
            sess.common.send_msg_encrypt(Message::build_key_update_notify());

            let write_key = self.key_schedule.next_server_application_traffic_secret();
            let scs = sess.common.get_suite_assert();
            sess.common.record_layer.set_message_encrypter(cipher::new_tls13_write(scs, &write_key));
        }
    }
}

#[cfg(feature = "quic")]
pub struct ExpectQUICTraffic {
    _fin_verified: verify::FinishedMessageVerified,
}

#[cfg(feature = "quic")]
impl hs::State for ExpectQUICTraffic {
    fn check_message(&self, m: &Message) -> hs::CheckResult {
        Err(TLSError::InappropriateMessage {
            expect_types: Vec::new(),
            got_type: m.typ,
        })
    }

    fn handle(self: Box<Self>, _: &mut ServerSessionImpl, _: Message) -> hs::NextStateOrError {
        unreachable!("check_message always fails");
    }
}
